网站定制开发优点,岳阳君山,一元手游平台app,免费素材库网站观察者模式
观察者模式#xff0c;又叫做发布–订阅模式(Publish/Subscribe)模式
观察者模式定义了一种一对多的依赖关系#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生改变时#xff0c;会通知所有的观察者对象#xff0c;使他们能够自动更…观察者模式
观察者模式又叫做发布–订阅模式(Publish/Subscribe)模式
观察者模式定义了一种一对多的依赖关系让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生改变时会通知所有的观察者对象使他们能够自动更新自己。
观察者模式(Observer)结构图 Subject类可翻译为主题或抽象通知者一般用一个抽象类或一个接口实现。它把所有对观察者对象的引用保留在一个聚集里每个主题都可以有任何数量的观察者。抽象主题提供一个接口可以增加和删除观察者对象。
// 抽象通知者
public abstract class Subject {private ListObserver list new ArrayList();// 状态protected String subjectState;// 增加观察者public void attatch(Observer observer) {list.add(observer);}// 减少观察者public void detach(Observer observer) {list.remove(observer);}// 通知观察者public void notifyObserver() {for (Observer item : list) {item.update();}}public String getSubjectState() {return subjectState;}public void setSubjectState(String subjectState) {this.subjectState subjectState;}
}Observer类抽象观察者为所有的具体观察者定义一个接口在得到主题的通知时更新自己。这个接口叫做更新接口。抽象观察者一般用一个抽象类或一个接口实现。更新接口通常包含一个update()方法这个方法叫做更新方法。
// 抽象观察者
public abstract class Observer { public abstract void update();
}ConcreteSubject类具体主题或具体通知者将有关状态存入具体观察者对象在具体主题的内部状态改变时给所有登记的观察者发出通知。具体主题角色通常用一个子类实现。
// 具体主题或具体通知者
public class ConcreteSubject extends Subject {
}ConcreteObserver类具体观察者实现抽象观察者角色所要求的更新接口以便使本身的状态与主题的状态相协调。具体观察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常使用一个子类实现。
// 具体观察者
public class ConcreteObserver extends Observer {private String name;private Subject sub;public ConcreteObserver(String name, Subject sub) {this.name name;this.sub sub;}Overridepublic void update() {System.out.println(观察者this.name 的新状态是this.sub.getSubjectState());}
}客户端调用
Subject subject new ConcreteSubject();
subject.attatch(new ConcreteObserver(nameX, subject));
subject.attatch(new ConcreteObserver(nameY, subject));
subject.attatch(new ConcreteObserver(nameZ, subject));subject.notifyObserver();案例
那么现在举一个简单的例子某公司中某部门几个员工在上班期间趁着老板不在炒股、看NBA等等开始摸鱼并且通过买一些小零食贿赂前台小姐姐当老板回来时通知他们一声。使用观察者模式如何实现呢
那么首先分清楚角色划分具体主题或具体通知者就是我们的前台小姐姐那么具体观察者就是部门的几个员工。
我们的抽象通知者Subject类基本是不需要改变的直接拿上面的的代码就行然后设置个名称区分下就行。
Subject抽象通知者
// 抽象通知者
public abstract class Subject {private ListObserver list new ArrayList();protected String subjectState;protected String name;public Subject(String name) {this.name name;}// 增加观察者public void attatch(Observer observer) {list.add(observer);}// 减少观察者public void detach(Observer observer) {list.remove(observer);}// 通知观察者public void notifyObserver() {for (Observer item : list) {item.update();}}public String getSubjectState() {return subjectState;}public void setSubjectState(String subjectState) {this.subjectState subjectState;}
}具体通知者
// 前台小姐姐
public class Secretary extends Subject {public Secretary(String name) {super(name);}
}抽象观察者
// 看股票的同事
public class StockObserver extends Observer {public StockObserver(String name, Subject sub) {super(name, sub);}Overridepublic void update() {System.out.println(super.sub.name super.sub.getSubjectState() super.name 快关闭股票行情开始工作);}
}// 看NBA的同事
public class NBAObserver extends Observer {public NBAObserver(String name, Subject sub) {super(name, sub);}Overridepublic void update() {System.out.println(super.sub.name super.sub.getSubjectState() super.name 快关闭NBA直播开始工作);}
}客户端调用
Subject subject new Secretary(前台小姐姐);
subject.attatch(new StockObserver(张三, subject));
subject.attatch(new StockObserver(李四, subject));
subject.attatch(new NBAObserver(王五, subject));
subject.setSubjectState(老板回来了);subject.notifyObserver();结果
前台小姐姐老板回来了张三快关闭股票行情开始工作
前台小姐姐老板回来了李四快关闭股票行情开始工作
前台小姐姐老板回来了王五快关闭NBA直播开始工作Java内置接口实现
实际上java已经为观察者模式准备好了相关的接口和抽象类了。观察者接口java.util.Observer和通知者java.util.Observable。有了这些Java内置的代码我们只需要扩展或继承Observable并且告诉它什么时候应该通知观察者就OK了。
那么后边考虑到如果有多个通知者的情况下为了避免需要在update()方法中对通知者进行强转中间又加了一层Subject类。
代码结构图 那么看看具体实现过程
抽象通知者类
// 抽象通知者
public abstract class Subject extends Observable {private ListObserver list new ArrayList();protected String subjectState;protected String name;public Subject(String name) {this.name name;}public String getSubjectState() {return subjectState;}public void setSubjectState(String subjectState) {this.subjectState subjectState;super.setChanged(); // 改变通知者的状态super.notifyObservers(); // 调用父类的方法通知所有的观察者}
}具体通知者
// 前台小姐姐
public class Secretary extends Subject {public Secretary(String name) {super(name);}
}具体观察者类
// 看股票的同事
public class StockObserver implements Observer {protected String name;public StockObserver(String name) {this.name name;}Overridepublic void update(Observable o, Object arg) {Subject sub (Subject) o;System.out.println(sub.name sub.getSubjectState() this.name 快关闭股票行情开始工作);}}// 看NBA的同事
public class NBAObserver implements Observer { protected String name;public NBAObserver(String name) {this.name name;}Overridepublic void update(Observable o, Object arg) {Subject sub (Subject) o;System.out.println(sub.name sub.getSubjectState() this.name 快关闭NBA直播开始工作);}
}客户端调用
Subject subject new Secretary(前台小姐姐);
subject.addObserver(new StockObserver(张三));
subject.addObserver(new StockObserver(李四));
subject.addObserver(new NBAObserver(王五));
subject.setSubjectState(老板回来了);subject.notifyObservers();特点
使用观察者模式的动机是什么呢 将一个系统分割成一系列相互协作的类有一个很不好的副作用那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合这样会给维护、扩展和重用都带来不便。 当一个对象的改变需要同时改变其他对象时而它不知道具体有多少个对象有待改变时应该考虑使用观察者模式。 抽象模型有两个方面其中一方面依赖于另一方面这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。 观察者模式所作的工作其实就是在解耦合。让耦合的双方都依赖于抽象而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。