设计模式之观察者模式
来源:互联网 发布:凭都网软件 编辑:程序博客网 时间:2024/06/03 20:59
观察者模式主要用于当一个类对象改变时,多个对象做出相应的反应。例如,Android广播使用的就时观察者模式。当一些对象接受到消息,做出一系列的反应。
现在,我们模拟一个观察者的使用场景。
那是长征期间,红军战士为了躲避老蒋的追击,每到一处都会有警卫站岗,一旦警卫发现敌情就会通知他的战友们准备战斗,当他的战友得到通知时就会做出相应的行动。
在这里,警卫是通知者,他的战友们就是观察者, 如何实现呢?看下面的代码
定义一个红军类
//红军类public class RedArmy { private String name ; public RedArmy(String name){ this.name = name ; } //进行相关更新操作 public void update(){ System.out.println("我是"+name+",我接收到消息了。"); } public String getName(){ return this.name ; }}
定义一个警卫类
//警卫类public class Guard { private List<RedArmy> redArmies ; public Guard(){ redArmies = new ArrayList<>(); } //增加一个将要通知的战友 public void addRedArmy(RedArmy redArmy){ this.redArmies.add(redArmy); } //如果一个战友牺牲了,就不再通知他了 public void removeArmy(RedArmy redArmy){ this.redArmies.remove(redArmy); } public void notifyArmy(){ for (RedArmy redArmy : redArmies) { redArmy.update(); //进行相应的操作 } }}
测试类
public class Test { public static void main(String[] args) { RedArmy r1 = new RedArmy("红军战士1"); //实例化一个红军战士 RedArmy r2 = new RedArmy("红军战士2");//实例化一个红军战士 Guard guard = new Guard(); //实例化一个警卫 guard.addRedArmy(r1); //将红军战士1作为警卫的通知对象 guard.addRedArmy(r2); //将红军战士2作为警卫的通知对象 guard.notifyArmy(); //通知红军战士 }}
运行结果
我是红军战士1,我接收到消息了。我是红军战士2,我接收到消息了。
从程序运行上,已经完全达到我们预期的效果,也满足我们的要求。但是,此时如果警卫不在,让侦察兵来通知,接下来我们该怎么做呢?对于码农的我们,抡起键盘就是再写一个和警卫类似的一个类。那么如果再换人呢,还要再写吗?此时我们应该想到面向对象中的抽象的特性了。我们可以抽象出一个通知类,可以进行通知。无论是警卫还是侦察兵,只要实现了抽象就可以了。其实这就是所谓的高大上的依赖抽象而不依赖具体。
定义一个抽象通知者类
//抽象的通知者public abstract class Subject { protected List<RedArmy> redArmys; public Subject() { this.redArmys = new ArrayList<>(); } public void addRedArmy(RedArmy redArmy){ this.redArmys.add(redArmy); } public void removeRedArmy(RedArmy redArmy){ this.redArmys.remove(redArmy); } public void notifyGuard(){ for (RedArmy redArmy:redArmys) { redArmy.update(); } }}
修改警卫类,继承抽象通知者类
//警卫类public class Guard extends Subject{}
测试类
public class Test { public static void main(String[] args) { RedArmy r1 = new RedArmy("红军战士1"); //实例化一个红军战士 RedArmy r2 = new RedArmy("红军战士2");//实例化一个红军战士 //这里直接sj = new Guard();如果换成侦察兵,只需改动sj = new 侦察兵();就可以了。 Subject sj = new Guard(); ////实例化一个警卫 sj.addRedArmy(r1); //将红军战士1作为警卫的通知对象 sj.addRedArmy(r2); //将红军战士2作为警卫的通知对象 sj.notifyArmy(); //通知红军战士 }}
通过我们的第一步修改已经完成了通知者依赖抽象,现在看看代码还有什么问题了吗?没错,还是存在着依赖具体的缺陷。假设现在追击的不是老蒋而是小日本了,小日本可是非常毒的,他们不仅杀害红军战士,还伤害老百姓,所以此时警卫还要通知老百姓。代码怎么改呢?难道我们在通知者中再加一个List<老百姓>的集合吗?确实是可以,但是如果还要再去通知民兵呢?还要再修改通知者吗,这已经违背了设计模式的开放-封闭原则(对扩展开放,对修改关闭)我们尽量不修改就不去修改。
分析一下,无论是红军战士还是老百姓,还是民兵他们在这都是观察者,就是当他们一旦得到消息就会行动。所以我们抽象出一个观察者类。
抽象观察者类
//抽象观察者类public abstract class Observer { protected String name ; public Observer(String name){ this.name = name ; } public abstract void update();}
修改红军战士类,继承抽象观察者类即可。
//红军类public class RedArmy extends Observer{ public RedArmy(String name) { super(name); } @Override public void update() { System.out.println("我是"+name+",我需要开始战斗了。"); }}
添加老百姓类
//老百姓类public class Civilian extends Observer { public Civilian(String name) { super(name); } @Override public void update() { System.out.println("我是"+name+",我要转移了。"); }}
添加民兵类
//民兵类public class Militia extends Observer{ public Militia(String name) { super(name); } @Override public void update() { System.out.println("我是"+name+",我要协助红军战士们参加战斗了"); }}
最后再修改通知者类,让通知者依赖观察者的抽象,而不是具体实现
//抽象的通知者public abstract class Subject { //依赖观察者的抽象 protected List<Observer> observers ; public Subject() { this.observers = new ArrayList<>(); } public void addObserver(Observer observer){ this.observers.add(observer); } public void removeObserver(Observer observer){ this.observers.remove(observer); } public void notifyArmy(){ for (Observer observer:observers) { observer.update(); } }}
测试类
public class Test { public static void main(String[] args) { Observer r1 = new RedArmy("红军战士1"); //实例化一个红军战士 Observer r2 = new RedArmy("红军战士2");//实例化一个红军战士 Observer m1 = new Militia("民兵战士"); //实例化一个民兵战士 Observer c1 = new Civilian("老百姓"); //实例化一个老百姓 Subject sj = new Guard(); ////实例化一个警卫 sj.addObserver(r1); //将红军战士1作为警卫的通知对象 sj.addObserver(r2); //将红军战士2作为警卫的通知对象 sj.addObserver(m1);//将民兵战士作为警卫的通知对象 sj.addObserver(c1);//将老百姓作为警卫的通知对象 sj.notifyArmy(); //通知观察者 }}
运行结果
我是红军战士1,我需要开始战斗了。我是红军战士2,我需要开始战斗了。我是民兵战士,我要协助红军战士们参加战斗了我是老百姓,我要转移了。
我们可以看到完全可以实现我们的功能,当警卫发现出现敌情时,可以同时通知老百姓,红军战士,民兵,而他们由于身份不同,责任不同,所以做出了不同的选择。
现在即使就是侦察兵和警卫都不在了,我们只需要有一个类继承了通知者就完全可以取代警卫的工作。
- 设计模式之-观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- 设计模式之观察者模式
- Spring Jackson 反序列化Date时遇到的问题
- hdu6058 Kanade's sum
- 暑假记录
- qmake手册——qmake语言
- SLAM实战 RGB-D SLAM V2
- 设计模式之观察者模式
- 【笔记】Android WallpaperService实现视频壁纸、相机桌面
- 通讯录静态版本
- 4.编写一个通用的 Makefile :-)
- Grafana、collectd 和 InfluxDB 构建监控系统
- 闭合浮动,元素浮动或绝对定位后失去文档流的友好解决办法
- sqlserver中的表值函数和标量值函数
- hdu 1812
- C++面向对象(1)