戏说模式之:观察者模式(三体)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了戏说模式之:观察者模式(三体)相关的知识,希望对你有一定的参考价值。
定义
观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)
是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。
这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。
观察者模式结构
摘抄于Head First设计模式
该设计方式充分展现了松耦合的威力,当两个对象之间松耦合,它们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让主题和观察者直接松耦合。
关于观察者的一切主题只知道观察者实现了某个接口(IObserver接口)。主题不需要知道具体的观察者是谁,内部实现了那些细节。
任何时候我们都可以添加新的观察者。因为主题唯一依赖的是一个实现IObserver接口的列表,所以我们可以随时添加或删除观察者,主题并不受任何影响。当有新的观察者出现的时候,主题的代码不需要做任何更改。只需要新的观察者实现IObserver接口即可
理解
我们先引入一个场景,《三体》中三体星人向地球发送了一颗质子来监视和锁定地球,同时派遣三体舰队前来占领地球。质子把地球的情况时时发送给三体星和三体舰队。在这里地球是信息载体,三体星和三体舰队就是具体的观察者,质子则是地球信息收集和分发着。质子可以自行决定是否分发信息到三体星或三体舰队。
《三体》场景的结构图
该结构图中定义了主题接口(ISubject),主题的实现接口(ConcreteSubject),观察者接口(IObserver),三体星观察者(ThreeBodyPlanet),三体舰队观察者(ThreeBodyFleet),地球资源bean(Earth),具体调用客户端质子(Proton)
具体实现
主题接口
/**
* 主题,每个观察者的管理接口
*/
public interface ISubject {
public void addObserver(IObserver observer);
public void deleteObserver(IObserver observer);
public void notifyObserver(Earth earth);
}
主题具体实现
/**
* 主题的具体实现类
*/
public class ConcreteSubject implements ISubject {
List<IObserver> observers ;
public ConcreteSubject(){
this.observers = new ArrayList<IObserver>();
}
@Override
public void addObserver(IObserver observer) {
this.observers.add(observer);
}
@Override
public void deleteObserver(IObserver observer) {
this.observers.remove(observer);
}
@Override
public void notifyObserver(Earth earth) {
for(IObserver observer : observers){
observer.update(earth);
}
}
public void timeUp(Earth earth){
this.notifyObserver(earth);
}
}
观察者接口
/**
* 观察者接口,只有一个update方法
*/
public interface IObserver {
public void update(Earth earth);
}
地球资源实体
/**
* 地球实体bean
*/
public class Earth {
//武器
private String weapon;
//人口
private long population;
//技术
private String technology;
//水含量
private float water;
//温度
private float temperature;
//陆地
private float land;
public String getWeapon() {
return weapon;
}
public void setWeapon(String weapon) {
this.weapon = weapon;
}
public long getPopulation() {
return population;
}
public void setPopulation(long population) {
this.population = population;
}
public String getTechnology() {
return technology;
}
public void setTechnology(String technology) {
this.technology = technology;
}
public float getWater() {
return water;
}
public void setWater(float water) {
this.water = water;
}
public float getTemperature() {
return temperature;
}
public void setTemperature(float temperature) {
this.temperature = temperature;
}
public float getLand() {
return land;
}
public void setLand(float land) {
this.land = land;
}
}
三体星(观察者)
/**
* 三体星球观察者
*/
public class ThreeBodyPlanet implements IObserver {
@Override
public void update(Earth earth) {
System.out.println("======三体星球观察者====");
StringBuffer buf = new StringBuffer();
buf.append("水资源:"+earth.getWater()+"亿立方千米,");
buf.append("温度:"+earth.getTemperature() + "℃,");
buf.append("陆地:"+earth.getLand() + "亿平方公里,");
buf.append("人口:"+earth.getPopulation() + "亿");
System.out.println(buf.toString());
}
}
三体舰队(观察者)
/**
* 三体舰队观察者
*/
public class ThreeBodyFleet implements IObserver{
@Override
public void update(Earth earth) {
System.out.println("======三体舰队观察者====");
StringBuffer buf = new StringBuffer();
buf.append("武器:"+earth.getWeapon()+",");
buf.append("科技:"+earth.getTechnology() + ",");
buf.append("人口:"+earth.getPopulation() + "亿");
System.out.println(buf.toString());
}
}
质子(信息收集发布)
/**
* 向三体汇报地球情况的质子
*/
public class Proton {
@Test
public void report(){
Earth earth = new Earth();
earth.setLand(5.11f);
earth.setPopulation(70);
earth.setTechnology("能够利用核能,未掌握曲率引擎,无星际旅行能力");
earth.setTemperature(15.8f);
earth.setWater(14f);
earth.setWeapon("最高级的攻击是核裂变");
ConcreteSubject concreteSubject = new ConcreteSubject();
//三体舰队
ThreeBodyFleet threeBodyFleet = new ThreeBodyFleet();
//三体星
ThreeBodyPlanet threeBodyPlanet = new ThreeBodyPlanet();
//添加具体的观察者(三体舰队)
concreteSubject.addObserver(threeBodyFleet);
//添加具体的观察者(三体星)
concreteSubject.addObserver(threeBodyPlanet);
//调用通知(时间到了通知)
concreteSubject.timeUp(earth);
//因为人类新掌握了核聚变,紧急通知三体舰队(三体星不通知)
earth.setWeapon("掌握了核聚变");
concreteSubject.deleteObserver(threeBodyPlanet);
concreteSubject.timeUp(earth);
}
}
观察者模式优点
1、主题和具体的观察者之间松耦合的设计,使得观察者模式有很强的扩展性。
2、在客户端调用时候可以随意装配观察者
观察者模式的缺点
1、如果一个主题有非常多的直接或间接的观察者,则所有观察者都通知到会消耗很长时间。
2、如果多个主题之间有循环依赖的话,观察者可能 触发循环调用导致系统死掉。
以上是关于戏说模式之:观察者模式(三体)的主要内容,如果未能解决你的问题,请参考以下文章