Java设计模式之java观察者模式详解

目录
  • 引言
  • 介绍
  • 角色
  • 原理类图
  • 微信订阅号的案例
  • 总结
    • 优点
    • 缺点
  • 适用场景
  • 观察者模式的典型应用
    • JDK 提供的观察者接口
    • Guava EventBus 中的观察者模式
    • Spring ApplicationContext 事件机制中的观察者模式
  • 参考文章
  • 总结

引言

观察者模式是设计模式中的 “超级模式”,其应用随处可见,我们以微信公众号为例。

微信公众号有服务号、订阅号和企业号之分。当我们在公众号上发布一篇博文推送时,订阅的用户都能够在我发布推送之后及时接收到推送,即可方便地在手机端进行阅读。

介绍

观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式是一种对象行为型模式。

观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

观察者模式包含观察目标和观察者两类对象,**一个目标可以有任意数目的与之相依赖的观察者,**一旦观察目标的状态发生改变,所有的观察者都将得到通知。

  • 一般是多对一依赖,即一个被观察者,和多个观察者
  • 一旦大忽悠更新了公众号,所有订阅其公众号的粉丝都会接收到更新推送

角色

Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify()。目标类可以是接口,也可以是抽象类或具体类。

ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。

Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者。

ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法。通常在实现时,可以调用具体目标类的attach()方法将自己添加到目标类的集合中或通过detach()方法将自己从目标类的集合中删除。

原理类图

微信订阅号的案例

首先需要一个订阅者接口(观察者),该接口有一个 receive 方法,用于接收公众号推送通知

//订阅者---观察者
public interface Subscriber
{
    //接收发布者发布消息的方法
    public void receive();
}

然后是一个微信客户端(具体观察者),实现了 receive 方法

//处理微信订阅的业务逻辑
public class WeChatSub implements Subscriber
{
    //当前订阅者的名字
    private String subName;
    WeChatSub(String subName)
    {
        this.subName=subName;
    }
    @Override
    public void receive(String publisher, String passageName) {
       //接收到推送消息时的具体业务逻辑操作
        System.out.println(String.format("用户[%s] ,  接收到[%s]的订阅号推送," +
                "推送文章为:%s ",subName,publisher,passageName));
    }
}

发布者类(目标,被观察对象),该类维护了一个订阅者列表,实现了订阅、取消订阅、通知所有订阅者等功能

//发布者--被观察的对象Subject
public class Publisher
{
    //存放所有需要通知的观察者
   static private List<Subscriber> subscribers=new ArrayList<>();
   //记录是否发布的状态,默认false
    static private  Boolean pubStatus=false;
    protected void subscribe(Subscriber subscriber) {
        this.subscribers.add(subscriber);
    }
    protected void unsubscribe(Subscriber subscriber) {
        if (this.subscribers.contains(subscriber)) {
            this.subscribers.remove(subscriber);
        }
    }
    protected void notifySubscribers(String publisher, String articleName) {
        if (this.pubStatus == false) {
            return;
        }
        for (Subscriber subscriber : this.subscribers) {
            subscriber.receive(publisher, articleName);
        }
        this.clearPubStatus();
    }
    protected void setPubStatus() {
        this.pubStatus = true;
    }
    protected void clearPubStatus() {
        this.pubStatus = false;
    }
}

微信公众号类(具体目标),该类提供了 publishArticles 方法,用于发布推送,当文章发布完毕时调用父类的通知所有订阅者方法

public class WeChatPublisher extends  Publisher
{
    private String name;
    public WeChatPublisher(String name) {
        this.name = name;
    }
    public void publishArticles(String articleName, String content) {
        System.out.println(String.format("\n<%s>微信公众号 发布了一篇推送,文章名称为 <%s>,内容为 <%s> ", this.name, articleName, content));
        setPubStatus();
        notifySubscribers(this.name, articleName);
    }
}

客户端测试

//客户端
public class Client
{
    public static void main(String[] args) {
        //创建一个发布者
        WeChatPublisher dhy=new WeChatPublisher("大忽悠");
        //创建订阅者
        Subscriber sub1=new WeChatSub("小朋友");
        Subscriber sub2=new WeChatSub("小忽悠");
        Subscriber sub3=new WeChatSub("大朋友");
        //订阅大忽悠公众号
        dhy.subscribe(sub1);
        dhy.subscribe(sub2);
        dhy.subscribe(sub3);
        //大忽悠发布推送
        dhy.publishArticles("设计模式","观察者模式");
    }
}

总结

优点

  • 观察者模式可以实现表示层和数据逻辑层的分离,定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层充当具体观察者角色。
  • 观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者。由于观察目标和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
  • 观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。
  • 观察者模式满足 “开闭原则”的要求,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下,增加新的观察目标也很方便。

缺点

  • 如果一个观察目标对象有很多直接和间接观察者,将所有的观察者都通知到会花费很多时间。
  • 如果在观察者和观察目标之间存在循环依赖,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
  • 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

适用场景

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致一个或多个其他对象也发生改变,而并不知道具体有多少对象将发生改变,也不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

观察者模式的典型应用

JDK 提供的观察者接口

观察者模式在Java语言中的地位非常重要。在JDK的 java.util 包中,提供了 Observable 类以及 Observer 接口,它们构成了JDK对观察者模式的支持。

其中的 Observer 接口为观察者,只有一个 update 方法,当观察目标发生变化时被调用,其代码如下:

public interface Observer {
    void update(Observable o, Object arg);
}

Observable 类则为目标类,相比我们的示例中的 Publisher 类多了并发和NPE方面的考虑

public class Observable {
    private boolean changed = false;
    private Vector<Observer> obs = new Vector();
    public Observable() {
    }
    // 用于注册新的观察者对象到向量中
    public synchronized void addObserver(Observer var1) {
        if (var1 == null) {
            throw new NullPointerException();
        } else {
            if (!this.obs.contains(var1)) {
                this.obs.addElement(var1);
            }
        }
    }
    // 用于删除向量中的某一个观察者对象
    public synchronized void deleteObserver(Observer var1) {
        this.obs.removeElement(var1);
    }
    public void notifyObservers() {
        this.notifyObservers((Object)null);
    }
    // 通知方法,用于在方法内部循环调用向量中每一个观察者的update()方法
    public void notifyObservers(Object var1) {
        Object[] var2;
        synchronized(this) {
            if (!this.changed) {
                return;
            }
            var2 = this.obs.toArray();
            this.clearChanged();
        }
        for(int var3 = var2.length - 1; var3 >= 0; --var3) {
            ((Observer)var2[var3]).update(this, var1);
        }
    }
    // 用于清空向量,即删除向量中所有观察者对象
    public synchronized void deleteObservers() {
        this.obs.removeAllElements();
    }
    // 该方法被调用后会设置一个boolean类型的内部标记变量changed的值为true,表示观察目标对象的状态发生了变化
    protected synchronized void setChanged() {
        this.changed = true;
    }
    // 用于将changed变量的值设为false,表示对象状态不再发生改变或者已经通知了所有的观察者对象,调用了它们的update()方法
    protected synchronized void clearChanged() {
        this.changed = false;
    }
    // 返回对象状态是否改变
    public synchronized boolean hasChanged() {
        return this.changed;
    }
    // 返回向量中观察者的数量
    public synchronized int countObservers() {
        return this.obs.size();
    }
}

我们可以使用 Observable 类以及 Observer 接口来重新实现微信公众号示例。

增加一个通知类 WechatNotice,用于推送通知的传递

@Data
@AllArgsConstructor
public class WechatNotice {
    private String publisher;
    private String articleName;
}

然后改写 WeChatClient WeChatAccounts,分别实现JDK的 Observer 接口和继承 Observable

public class WeChatClient implements Observer {
    private String username;
    public WeChatClient(String username) {
        this.username = username;
    }
    @Override
    public void update(Observable o, Object arg) {
        //WeChatAccounts weChatAccounts = (WeChatAccounts) o;
        WechatNotice notice = (WechatNotice) arg;
        System.out.println(String.format("用户<%s> 接收到 <%s>微信公众号 的推送,文章标题为 <%s>", username, notice.getPublisher(), notice.getArticleName()));
    }
}
public class WeChatAccounts extends Observable {
    private String name;
    public WeChatAccounts(String name) {
        this.name = name;
    }
    public void publishArticles(String articleName, String content) {
        System.out.println(String.format("\n<%s>微信公众号 发布了一篇推送,文章名称为 <%s>,内容为 <%s> ", this.name, articleName, content));
        setChanged();
        notifyObservers(new WechatNotice(this.name, articleName));
    }
}

测试,与示例中的测试代码的区别在于调用的方法不同

public class Test {
    public static void main(String[] args) {
        WeChatAccounts accounts = new WeChatAccounts("大忽悠");
        WeChatClient user1 = new WeChatClient("张三");
        WeChatClient user2 = new WeChatClient("李四");
        WeChatClient user3 = new WeChatClient("王五");
        accounts.addObserver(user1);
        accounts.addObserver(user2);
        accounts.addObserver(user3);
        accounts.publishArticles("设计模式 | 观察者模式及典型应用", "观察者模式的内容...");
        accounts.deleteObserver(user1);
        accounts.publishArticles("设计模式 | 单例模式及典型应用", "单例模式的内容....");
    }
}

Guava EventBus 中的观察者模式

Guava 中的 EventBus 封装了友好的 “生产/消费模型”,通过非常简单的方式,实现了观察者模式中的监听注册,事件分发。

使用了 Guava EventBus 之后,如果需要订阅消息,不需要实现任何接口,只需在监听方法上加上 @Subscribe 注解即可,EventBus 提供了 registerunregister 方法用于注册与取消注册事件,当 EventBus 调用 post 方法时将把事件分发给注册的对象

使用 Guava 重新实现示例

@Data
@AllArgsConstructor
public class WechatNotice {
    private String publisher;
    private String articleName;
}
public class WeChatClient  {
    private String username;
    public WeChatClient(String username) {
        this.username = username;
    }
    @Subscribe
    public void listen(WechatNotice notice) {
        System.out.println(String.format("用户<%s> 接收到 <%s>微信公众号 的推送,文章标题为 <%s>", username, notice.getPublisher(), notice.getArticleName()));
    }
}
public class WeChatAccounts {
    private String name;
    private EventBus eventBus;
    public WeChatAccounts(String name) {
        this.name = name;
        this.eventBus = new EventBus();
    }
    public void publishArticles(String articleName, String content) {
        System.out.println(String.format("\n<%s>微信公众号 发布了一篇推送,文章名称为 <%s>,内容为 <%s> ", this.name, articleName, content));
        //post方法将会将被派发的消息,传递给所有的订阅者,并调用订阅者的监听方法
        this.eventBus.post(new WechatNotice(this.name, articleName));
    }
    public void register(WeChatClient weChatClient) {
        this.eventBus.register(weChatClient);
    }
    public void unregister(WeChatClient weChatClient) {
        this.eventBus.unregister(weChatClient);
    }
}

测试

public class Test {
    public static void main(String[] args) {
        WeChatAccounts accounts = new WeChatAccounts("小旋锋");
        WeChatClient user1 = new WeChatClient("张三");
        WeChatClient user2 = new WeChatClient("李四");
        WeChatClient user3 = new WeChatClient("王五");
        accounts.register(user1);
        accounts.register(user2);
        accounts.register(user3);
        accounts.publishArticles("设计模式 | 观察者模式及典型应用", "观察者模式的内容...");
        accounts.unregister(user1);
        accounts.publishArticles("设计模式 | 单例模式及典型应用", "单例模式的内容....");
    }
}

Spring ApplicationContext 事件机制中的观察者模式

spring的事件机制是从java的事件机制拓展而来,ApplicationContext 中事件处理是由 ApplicationEvent 类和 ApplicationListener 接口来提供的。如果一个Bean实现了 ApplicationListener 接口,并且已经发布到容器中去,每次 ApplicationContext 发布一个 ApplicationEvent 事件,这个Bean就会接到通知

  • ApplicationContext:事件源,其中的 publishEvent()方法用于触发容器事件
  • ApplicationEvent:事件本身,自定义事件需要继承该类,可以用来传递数据
  • ApplicationListener:事件监听器接口,事件的业务逻辑封装在监听器里面
@Data
public class WechatNotice extends ApplicationEvent {
    private String publisher;
    private String articleName;
    public WechatNotice(Object source, String publisher, String articleName) {
        super(source);
        this.publisher = publisher;
        this.articleName = articleName;
    }
}
public class WeChatClient implements ApplicationListener {
    private String username;
    public WeChatClient(String username) {
        this.username = username;
    }
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof WechatNotice) {
            WechatNotice notice = (WechatNotice) event;
            System.out.println(String.format("用户<%s> 接收到 <%s>微信公众号 的推送,文章标题为 <%s>", username, notice.getPublisher(), notice.getArticleName()));
        }
    }
    public void setUsername(String username) {
        this.username = username;
    }
}
public class WeChatAccounts implements ApplicationContextAware {
    private ApplicationContext ctx;
    private String name;
    public WeChatAccounts(String name) {
        this.name = name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ctx = applicationContext;
    }
    public void publishArticles(String articleName, String content) {
        System.out.println(String.format("\n<%s>微信公众号 发布了一篇推送,文章名称为 <%s>,内容为 <%s> ", this.name, articleName, content));
        ctx.publishEvent(new WechatNotice(this.name, this.name, articleName));
    }
}

在 resources 目录下创建 spring.xml 文件,填入下面的内容

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="WeChatAccounts" class="com.observer.sprintevent.WeChatAccounts" scope="prototype">
        <constructor-arg name="name" value=""></constructor-arg>
    </bean>
    <bean id="WeChatClient1" class="com.observer.sprintevent.WeChatClient">
        <constructor-arg name="username" value="张三"></constructor-arg>
    </bean>
    <bean id="WeChatClient2" class="com.observer.sprintevent.WeChatClient">
        <constructor-arg name="username" value="李四"></constructor-arg>
    </bean>
    <bean id="WeChatClient3" class="com.observer.sprintevent.WeChatClient">
        <constructor-arg name="username" value="王五"></constructor-arg>
    </bean>
</beans>

测试

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        WeChatAccounts accounts = (WeChatAccounts) context.getBean("WeChatAccounts");
        accounts.setName("大忽悠");
        accounts.setApplicationContext(context);
        accounts.publishArticles("设计模式 | 观察者模式及典型应用", "观察者模式的内容...");
    }
}

在此示例中 ApplicationContext 对象的实际类型为 ClassPathXmlApplicationContext,其中的与 publishEvent 方法相关的主要代码如下:

private ApplicationEventMulticaster applicationEventMulticaster;
public void publishEvent(ApplicationEvent event) {
    this.getApplicationEventMulticaster().multicastEvent(event);
    if (this.parent != null) {
        this.parent.publishEvent(event);
    }
}
ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
    return this.applicationEventMulticaster;
}
protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
        if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
            this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
        } else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
        }
    }

其中的 SimpleApplicationEventMulticaster 如下,multicastEvent 方法主要是通过遍历 ApplicationListener(注册由 AbstractApplicationEventMulticaster 实现),使用线程池框架 Executor 来并发执行 ApplicationListener 的 onApplicationEvent 方法,与示例本质上是一致的

public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
    private Executor taskExecutor;
    public void multicastEvent(final ApplicationEvent event) {
        Iterator var2 = this.getApplicationListeners(event).iterator();
        while(var2.hasNext()) {
            final ApplicationListener listener = (ApplicationListener)var2.next();
            Executor executor = this.getTaskExecutor();
            if (executor != null) {
                executor.execute(new Runnable() {
                    public void run() {
                        listener.onApplicationEvent(event);
                    }
                });
            } else {
                listener.onApplicationEvent(event);
            }
        }
    }
}

参考文章

springboot启动源码

设计模式 | 观察者模式及典型应用

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Java设计模式之观察者模式(Observer模式)

    一.观察者模式是什么? 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern).当一个对象被修改时,则会自动通知依赖它的对象.观察者模式属于行为型模式. 人话: 就像微信公众号推送消息,订阅的人能收到,没订阅的收不到,还可以取消/添加订阅 二.模式分析 2.1 四个角色 抽象主题(抽象被观察者角色):也就是一个抽象主题,它把所有对观察者对象的引用保存在一个集合中,每个主题都可以有任意数量的观察者.抽象主题提供一个接口,可以增加和删除观察者角色.一般用一个抽象类和接口来实现

  • Java设计模式之观察者模式_动力节点Java学院整理

    定义:定义对象间一种一对多的依赖关系,使得当每一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新. 类型:行为类模式 类图: 在软件系统中经常会有这样的需求:如果一个对象的状态发生改变,某些与它相关的对象也要随之做出相应的变化.比如,我们要设计一个右键菜单的功能,只要在软件的有效区域内点击鼠标右键,就会弹出一个菜单:再比如,我们要设计一个自动部署的功能,就像eclipse开发时,只要修改了文件,eclipse就会自动将修改的文件部署到服务器中.这两个功能有一个相似的地方,那就是一个对象

  • java设计模式之观察者模式

    观察者模式又称发布-订阅(Publish/Subscribe)模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己.将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象间的一致性.我们不希望为了维持一致性而使各类紧密耦合,这样会给维护.扩展和复用都带来不便.观察者模式所做的工作其实就是在解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体. 观察者模式是实际中应用比较广泛的模

  • JAVA中常用的设计模式:单例模式,工厂模式,观察者模式

    1.单例模式 每个类只能创建一个实例对象 Java Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在. 使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收(garbage collection). 好处: 第一.控制资源的使用,通过线程同步来控制资源的并发访问: 第二.控制实例产生的数量,达到节约资源的目的. 第三.作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不相关的两个线程或者进程

  • Java设计模式—观察者模式详解

    观察者模式 包括这个模式在内的接下来的四个模式,都是类和类之间的关系,不涉及到继承,学的时候应该 记得归纳,记得本文最开始的那个图.观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客或wiki时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你.其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系. 先来看看关系图: 我解释下这些类的作用:MySubject类就是我们的主对象,Obs

  • Java通俗易懂系列设计模式之观察者模式

    介绍 观察者模式是行为设计模式之一.当您对对象的状态感兴趣并希望在有任何更改时收到通知时,观察者设计模式非常有用.在观察者模式中,监视另一个对象状态的对象称为Observer,正在被监视的对象称为Subject. 根据GoF,观察者设计模式的意图是; 定义对象之间的一对多依赖关系,以便当一个对象更改状态时,将自动通知和更新其所有依赖项. Subject包含一个观察者列表,用于通知其状态的任何变化,因此它应该提供观察者可以注册和注销自己的方法.Subject还包含一种方法,用于通知所有观察者任何更

  • Java设计模式探究之观察者模式详解

    目录 1.观察者模式是什么 2.如何实现 3.代码实现 1)观察者接口 2)被观察者接口 3)观察者实现 4)被观察者实现 5)测试类 4.延伸拓展 1.观察者模式是什么 顾名思义,有两个对象,观察者和被观察者.当被观察者数据发生变化时,提醒观察者更新数据或状态. 2.如何实现 1)定义两个类,观察者和被观察者. 2)被观察者要维护一个集合,存放观察者对象.并且提供增删方法. 3)被观察者数据发生变化时,要调用观察者的方法,以便通知观察者更新数据或状态. 4)基于面向抽象原则,可以将观察者和被观

  • java 设计模式之适配器模式的详解

    java 设计模式之适配器模式的详解 前言: 适配器模式(Adapter Pattern)又叫做变压器模式,也叫做包装模式.包装模式还包括装饰模式. 在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类的接口适配成用户所期待的. 一个适配允许通常因为接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中. UML类图:  具体代码: public class Client { public static void main(String[] args)

  • Java设计模式之命令模式详解

    命令模式 定义:将请求封装成对象,这可以让你使用不同的请求.队列.或者日志来参数化其他对象. 何时使用命令模式?当需要将发出请求的对象和执行请求的对象解耦的时候,使用命令模式. 在被解耦的两者之间是通过命令对象进行沟通的.命令对象封装了接收者和一个或一组动作. 调用者通过调用命令对象的execute()方法发出请求,这会使接收者的动作被调用. 调用者可以接收命令当作参数,甚至在运行时动态地进行. 优点: 1.降低了系统耦合度. 2.新的命令可以很容易添加到系统中去. 缺点:使用命令模式可能会导致

  • Java设计模式之原型模式详解

    一.前言 原型模式是一种比较简单的模式,也非常容易理解,实现一个接口,重写一个方法即完成了原型模式.在实际应用中,原型模式很少单独出现.经常与其他模式混用,他的原型类Prototype也常用抽象类来替代. 该模式的思想就是将一个对象作为原型,对其进行复制.克隆,产生一个和原对象类似的新对象.在Java中,复制对象是通过clone()实现的,先创建一个原型类,通过实现Cloneable 接口 public class Prototype implements Cloneable { public

  • Java设计模式之代理模式详解

    一.代理模式 代理模式就是有一个张三,别人都没有办法找到他,只有他的秘书可以找到他.那其他人想和张三交互,只能通过他的秘书来进行转达交互.这个秘书就是代理者,他代理张三. 再看看另一个例子:卖房子 卖房子的步骤: 1.找买家 2.谈价钱 3.签合同 4.和房产局签订一些乱七八糟转让协议 一般卖家只在签合同的时候可能出面一下,其他的1,2,4都由中介去做.那你问这样有什么用呢? 首先,一个中介可以代理多个卖房子的卖家,其次,我们可以在不修改卖家的代码的情况下,给他实现房子加价.打广告等等夹带私货的

  • Java设计模式之单例模式示例详解

    目录 0.概述 1.饿汉式 1.1 饿汉式单例实现 1.2 破坏单例的几种情况 1.3 预防单例的破坏 2.枚举饿汉式 2.1 枚举单例实现 2.2 破坏单例 3.懒汉式 4.双检锁懒汉式 5.内部类懒汉式 6.JDK中单例的体现 0.概述 为什么要使用单例模式? 在我们的系统中,有一些对象其实我们只需要一个,比如说:线程池.缓存.对话框.注册表.日志对象.充当打印机.显卡等设备驱动程序的对象.事实上,这一类对象只能有一个实例,如果制造出多个实例就可能会导致一些问题的产生,比如:程序的行为异常.

  • java设计模式之单例模式的详解及优点

    java设计模式之单例模式 定义:如果一个类始终只能创建一个实例,那么这个类被称为单例类,这种设计模式被称为单例模式. Spring框架里面可以将所有生成的bean对象都设置为单例模式,只需要在配置Bean实例时指定scope="singleton"即可,或者不做配置默认即为单例模式. 我们可以创建一个小的Demo来演示单例模式的实现,只需要保证该类只能创建一个实例,我们可以用权限修饰符private修饰该类的构造器. 提供一个创建该类的接口,该接口只能用static修饰,类里面创建一

  • Java设计模式之单例模式实例详解【懒汉式与饿汉式】

    本文实例讲述了Java设计模式之单例模式.分享给大家供大家参考,具体如下: 单例模式就是产生一个对象实例,供外外部访问. 它的应用场景就是在这个类在全局真资源需要统一访问,否则会造成混乱时,才有必要设计成单例. 懒汉式,就是在使用这个对象时,才去查看这个对象是否创建,如果没创建就马上创建,如果已经创建,就返回这个实例. 饿汉式,在加载这个类的时候就先创建好一个对象实例,等待调用. 两者的优缺点也能猜到,使用懒汉式,在反应速度上肯定要比饿汉式慢. 但是这个对象如果不被调用,那就节省了cpu和内存资

  • JAVA设计模式之访问者模式详解

    在阎宏博士的<JAVA与模式>一书中开头是这样描述访问者(Visitor)模式的: 访问者模式是对象的行为模式.访问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以保持不变. 分派的概念 变量被声明时的类型叫做变量的静态类型(Static Type),有些人又把静态类型叫做明显类型(Apparent Type):而变量所引用的对象的真实类型又叫做变量的实际类型(Actual Type).比如: 复制代码 代码如下: List lis

  • java设计模式之工厂方法详解

    一.概念 工厂方法模式是类的创建模式,又叫虚拟构造子模式(virtual constructor) 或者多态性工厂模式. 二.模式动机 定义一个抽像的工厂,将产品的具体创建工作推迟到抽像工厂的具体子类中,有些产品的创建非常复杂,试想如果将所有具体产品的创建工作都像简单工厂一样放到一个静态工厂方法中,那么这个工厂方法将无比巨大,且当需要扩展增加新的产品时,就必须修改原先的工厂方法,违背了开-闭原则,而工厂方法模式,对于每个具体产品的创建都有一个具体的工厂来创建,如果新增产品,只需要新增一个实现抽像

随机推荐