Observer 观察者模式

在开发过程当中,咱们常常会碰到这样的需求:若是一个对象A的状态发生改变,某些与它相关的对象也要随之作出相应的变化。一般来讲,须要对象 A 能访问到这些对象,从而去调用更新方法,可是这是一种不受欢迎的会形成耦合的方式。为了低耦合,能够采用观察者模式。设计模式

定义

Observer 观察者模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在更改其状态时,会通知全部的观察者对象,使他们可以自动更新本身。一个主题对象能够对应多个观察者,而这些观察者以前没有相互联系,能够根据须要增长和删除观察者,使得系统更易于拓展。bash

结构

  • Subject:抽象主题。抽象主题角色把全部观察者对象保存在一个集合里,每一个主题均可以有任意数量的观察者,抽象主题提供一个接口,能够增长和删除观察者对象。
  • ConcreteSubject:具体主题。该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给全部订阅过的观察者发送通知。
  • Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在获得主题更改通知时更新本身。
  • ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在获得主题更改通知时更新自身的状态。

简单实现

  • 抽象主题类
abstract class Subject {
        private Vector obs = new Vector();


        public void addObserver(Observer obs){
            this.obs.add(obs);
        }
        public void delObserver(Observer obs){
            this.obs.remove(obs);
        }
        protected void notifyObserver(){
            for(Observer o: obs){
                o.update();
            }
        }
        public abstract void doSomething();
    }复制代码
  • 具体主题类
class ConcreteSubject extends Subject {
        public void doSomething(){
            System.out.println("被观察者事件反生");
            this.notifyObserver();
        }
    }复制代码
  • 抽象观察者
interface Observer {
        public void update();
    }复制代码
  • 具体观察者
class ConcreteObserver1 implements Observer {
        public void update() {
            System.out.println("观察者1收到信息,并进行处理。");
        }
    }
    class ConcreteObserver2 implements Observer {
        public void update() {
            System.out.println("观察者2收到信息,并进行处理。");
        }
    }复制代码
  • 使用
public class Client {
        public static void main(String[] args){
            Subject sub = new ConcreteSubject();
            sub.addObserver(new ConcreteObserver1()); //添加观察者1
            sub.addObserver(new ConcreteObserver2()); //添加观察者2
            sub.doSomething();
        }
    }复制代码

运行结果:post

被观察者事件反生
观察者1收到信息,并进行处理。
观察者2收到信息,并进行处理。

实例

NSNotificationCenter 和 NSNotificationui

iOS 中的通知机制是很是典型的观察者模式,全部的类能够经过 NSNotificationCenter 监听和发送 NSNotification,观察者和被观察者都无需知晓对方,只须要经过标记(例如 NotificationName)在 NSNotificationCenter 中找到监听该通知所对应的类,从而调用该类的方法。而且,在 NSNotificationCenter 中,观察者能够只订阅某一特定的通知,并对其作出响应,而不用对某一个类发送的全部通知都进行更新操做。NSNotificationCenter 对观察者的调用不是随机的,而是遵循注册顺序一一执行,而且在该线程内是同步的。this

@property (class, readonly, strong) NSNotificationCenter *defaultCenter;


- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSNotificationName)aName object:(nullable id)anObject;


- (void)postNotification:(NSNotification *)notification;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject;
- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;


- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(nullable NSNotificationName)aName object:(nullable id)anObjec复制代码

优缺点

优势

1. 解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变换都不会影响另外一边的变换。spa

2. 观察者模式符合“开闭原则”的要求,若须要引入新的观察者,无需对被观察对象进行修改线程

缺点

1. 若是一个观察目标对象有不少直接和间接的观察者的话,将全部的观察者都通知到会花费不少时间,同时,开发和调试的复杂程度提升设计

2. 若是在观察者和观察目标之间有循环依赖,有可能会进行循环调用,致使系统崩溃3d

和其余设计模式的对比

责任链模式

观察者模式也能够将通知链式分就会发,与责任链模式十分类似调试

1. 责任链模式中,每一个接收者都包含对另外一个接收者的引用,而观察者模式中,被观察者并不知晓观察者具体是谁

2. 在纯责任链模式中,只有一个接收者会对请求进行处理,观察者模式容许每一个观察者都进行处理

命令模式

1. 命令模式是一对一的关系,观察者模式是一对多的关系

2. 命令模式是经过发送命令让接收方来执行,而观察者模式中发出消息的类(被观察者)并不关心接收消息的类(观察者)会如何处理

中介者模式

中介者模式各个组件之间经过中介创建的是双向链接,而观察者模式的被观察者和观察者之间是单向的。

中模式与观察者模式难以被区分的缘由之一是中介者模式的一个流行实现依赖于观察者模式。中介对象扮演发布者的角色,组件充当观察者,订阅和取消订阅中介的事件。当以这种方式实现中介者模式时,它可能看起来很是相似于观察者模式。可是,中介者模式还能够用其余方式实现。例如,能够将全部组件永久连接到同一个中介对象。这个实现不像观察者模式,但仍然是中介者模式。

相关文章
相关标签/搜索