设计模式--观察者模式
1、观察者模式
观察者模式:定义对象间一种一对多的依赖关系,当一个对象状态发生变化时,所有依赖于它的对象都得到通知,并被自动更新。
2、观察者模式的结构
角色
主题(Subject):主题是一个接口,该接口规定了具体主题需要实现的方法,比如添加,删除观察者以及通知观察者的方法。
观察者(ObServer): 观察者是一个接口,该接口规定了具体观察者用来获得数据的方法。
具体主题(ConcreteSubject):具体主题是实现主题接口的类的一个实例,该实例包含观察者关心的数据,而且这些数据可能经常发生变化。具体主题需要使用一个集合来存放观察者的引用,以便数据变化时通知具体的观察者。
具体观察者(ConreteObserver):具体观察者是实现观察者接口的类的一个实例。具体观察者包含具体主题的引用,以便让具体主题将自己添加到具体主题的集合中,使自己成为具体主题的观察者,或者从具体主题的集合中将自己删除,不成为具体主题的观察者。
UML图
3、观察者模式举例
主题接口:Subject.java
<Observer>
观察者接口:Observer.java
1 package com.nick.pattern.observer;2 /**3 * @ 观察者接口4 * @author nick5 */6 public interface Observer {7 void response(); //相当于update()方法 8 }
具体主题类:Cat.java
1 package com.nick.pattern.observer; 2 3 import java.util.ArrayList; 4 5 /** 6 * @ 具体主题:猫(老鼠和狗是观察者,他们通过观察猫的行为,做出反应) 7 * @author nick 8 * 9 */10 public class Cat implements Subject {11 ArrayList<Observer> observers = new ArrayList<Observer>();12 13 @Override14 public void attach(Observer obs) {15 observers.add(obs);16 }17 18 @Override19 public void detach(Observer obs) {20 observers.remove(obs); 21 }22 23 @Override24 public void cry() { //通知方法25 System.out.print("猫叫:");26 System.out.println("喵喵喵");27 for(Observer obs:observers) {28 obs.response();29 }30 }31 }
具体观察者:Dog.java
1 package com.nick.pattern.observer; 2 /** 3 * @ 具体观察者: 狗 4 * @author nick 5 * 6 */ 7 public class Dog implements Observer{ 8 9 @Override10 public void response() {11 System.out.print("狗叫:");12 System.out.println("汪汪汪");13 }14 15 }
具体观察者:Mouse.java
1 package com.nick.pattern.observer; 2 /** 3 * @ 具体观察者:老鼠 4 * @author nick 5 * 6 */ 7 public class Mouse implements Observer{ 8 9 @Override10 public void response() {11 System.out.print("老鼠跑:");12 System.out.println("跑跑跑");13 }14 15 }
主程序:Application.java
1 package com.nick.pattern.observer; 2 /** 3 * @ 主程序 4 * @author nick 5 * 6 */ 7 public class Application { 8 9 public static void main(String[] args) {10 Subject cat = new Cat();11 Observer dog = new Dog();12 Observer mouse = new Mouse();13 cat.attach(dog);14 cat.attach(mouse);15 16 cat.cry();//触发通知方法17 }18 19 }
运行结果:
4、观察者模式的优缺点
优点1: 具体主题和观察者是松耦合的关系。由于主题接口仅仅依赖与观察者接口,因此具体主题只是知道他的观察者是实现观察者接口的某个类的实例,但不需要知道是哪个类。
优点2:具体观察者只需要知道它依赖的主题是实现主题接口的某个实例即可,不需要知道具体是哪个类。
优点3:观察者模式满足“开-闭”原则。主题接口(Subject)仅仅依赖于观察者接口(Observer)。这样具体主题的类也仅仅依赖于观察者接口,增加新的实现观察者接口的类,不必修改创建具体主题的类的代码:
新增加一个观察者Pig.java
1 package com.nick.pattern.observer; 2 /** 3 * @ 新增的观察者Pig 4 * @author nick 5 */ 6 public class Pig implements Observer{ 7 8 @Override 9 public void response() {10 System.out.println("猪叫:");11 System.out.println("咯咯咯");12 }13 14 }
只需要在主程序中添加这两行代码