设计模式-观察者模式(Observer Pattern)
观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
观察者模式在实现时,有两种方式,一种是推(push),一种是拉(pull)。
一直在用,却不知道什么是观察者模式。看到一篇文章,关于观察者模式的,说白了就是一个对象(被观察者)持有一堆对象(观察者)的引用,这些引用都放在一个列表中,当被观察者的状态改变时,就调用引用(观察者)的 update() 方法,让所有的观察者知道被观察者的状态改变了,然后自己也跟着变化。
其中关键点:
1. 一对多的关系,一个被观察者(object),一个或者多个观察者(observer)
2. 被观察者持有每个观察者的引用
3. 被观察者有注册和取消注册的方法
4. 在被观察者的类中,用列表存放观察者的引用
5. 当被观察者的状态改变时,调用相关的 notify() 方法,在 notify() 方法中调用每个观察者的 update() 方法来让观察者知道该事件。
自己撸了一段代码:(使用的是交通灯的案例,
1. 交通灯是被观察者,汽车是观察者
2. 当白天的时候需要看红绿灯,交通灯状态为绿色时,汽车行驶,交通灯状态为红色时,汽车等待
3. 当凌晨12点到4点的时候,不需要看红绿灯,可以自由通过,这个时候交通灯的红绿灯就对汽车不起作用了。)
被观察者(TrafficLight)
1 public class TrafficLight { 2 private static final String TAG = "TrafficLight"; 3 private TrafficLightStatus defaultStatus = TrafficLightStatus.GREEN; 4 private List<ICar> observerList = new ArrayList<>(); 5 6 public TrafficLightStatus getLightStatus() { 7 return defaultStatus; 8 } 9 10 public void setTrafficLightStatus(TrafficLightStatus status) { 11 defaultStatus = status; 12 } 13 14 public void notifyStatusChange() { 15 if (observerList.size() > 0) { 16 for (int i = 0; i < observerList.size(); i++) { 17 if (defaultStatus == TrafficLightStatus.GREEN) { 18 observerList.get(i).move(); 19 } else { 20 observerList.get(i).stop(); 21 } 22 } 23 } 24 } 25 26 public void registerTrafficLight(ICar car) { 27 if (!observerList.contains(car)) { 28 observerList.add(car); 29 } 30 } 31 32 public void unRegisterTrafficLight(ICar car) { 33 if (observerList.contains(car)) 34 observerList.remove(car); 35 } 36 }
观察者(ICar)
1 public interface ICar { 2 void move(); 3 void stop(); 4 }
观察者的实现类(ToytaCar...)
1 public class ToytaCar implements ICar { 2 private static final String TAG = "ToytaCar"; 3 4 @Override 5 public void move() { 6 Log.e(TAG, "ToytaCar,绿灯,行驶"); 7 } 8 9 @Override 10 public void stop() { 11 Log.e(TAG, "ToytaCar,红灯,等待"); 12 } 13 }
MainActivity,4个 Button,分别是注册,取消注册,状态改变(绿灯,红灯)
1 public class MainActivity extends AppCompatActivity implements View.OnClickListener { 2 private List<ICar> carList = new ArrayList<>(); 3 Button btnRedLight, btnGreenLight, btnFreeLight, btnLimitLight; 6 TrafficLight trafficLight; 7 ICar toytaCar, nissanCar, mazdaCar, hondaCar, fordCar, bydCar, bmwCar, audiCar; 8 9 @Override 10 protected void onCreate(Bundle savedInstanceState) { 11 super.onCreate(savedInstanceState); 12 setContentView(R.layout.activity_main); 23 btnRedLight = (Button) findViewById(R.id.btn_red_light); 24 btnGreenLight = (Button) findViewById(R.id.btn_green_light); 25 btnFreeLight = (Button) findViewById(R.id.btn_free_light); 26 btnLimitLight = (Button) findViewById(R.id.btn_limit_light); 27 btnRedLight.setOnClickListener(this); 28 btnGreenLight.setOnClickListener(this); 29 btnFreeLight.setOnClickListener(this); 30 btnLimitLight.setOnClickListener(this); 31 trafficLight = new TrafficLight(); 32 toytaCar = new ToytaCar(); 33 nissanCar = new NissanCar(); 34 mazdaCar = new MazdaCar(); 35 hondaCar = new HondaCar(); 36 fordCar = new FordCar(); 37 bydCar = new BYDCar(); 38 bmwCar = new BWMCar(); 39 audiCar = new AudiCar(); 40 carList.add(toytaCar); 41 carList.add(nissanCar); 42 carList.add(mazdaCar); 43 carList.add(hondaCar); 44 carList.add(bydCar); 45 carList.add(bmwCar); 46 carList.add(audiCar); 47 carList.add(fordCar);49 } 50 51 @Override 52 public void onClick(View v) { 53 switch (v.getId()) { 54 case R.id.btn_green_light: 55 trafficLight.setTrafficLightStatus(TrafficLightStatus.GREEN); 56 trafficLight.notifyStatusChange(); 57 break; 58 case R.id.btn_red_light: 59 trafficLight.setTrafficLightStatus(TrafficLightStatus.RED); 60 trafficLight.notifyStatusChange(); 61 break; 62 case R.id.btn_free_light: 63 for (int i = 0; i < carList.size(); i++) { 64 trafficLight.unRegisterTrafficLight(carList.get(i)); 65 } 66 break; 67 case R.id.btn_limit_light: 68 for (int i = 0; i < carList.size(); i++) { 69 trafficLight.registerTrafficLight(carList.get(i)); 70 } 71 break; 72 default: 73 break; 74 } 75 } 76 }
log 输出:
1. 当点击按钮-看红绿灯(注册),点击红绿灯按钮就可以调用 ICar 的 move() 或者 stop() 方法,打印出来日志
1 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/ToytaCar: ToytaCar,红灯,等待 2 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/NissanCar: NissanCar,红灯,等待 3 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/MazdaCar: MazdaCar,红灯,等待 4 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/HondaCar: HondaCar,红灯,等待 5 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/BYDCar: BYDCar,红灯,等待 6 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/BWMCar: BWMCar,红灯,等待 7 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/AudiCar: AudiCar,红灯,等待 8 01-09 22:32:54.454 6900-6900/cc.lijingbo.pattern_observer E/FordCar: FordCar,红灯,等待 9 01-09 22:32:56.844 6900-6900/cc.lijingbo.pattern_observer E/ToytaCar: ToytaCar,绿灯,行驶 10 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/NissanCar: NissanCar,绿灯,行驶 11 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/MazdaCar: MazdaCar,绿灯,行驶 12 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/HondaCar: HondaCar,绿灯,行驶 13 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/BYDCar: BYDCar,绿灯,行驶 14 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/BWMCar: BWMCar,绿灯,行驶 15 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/AudiCar: AudiCar,绿灯,行驶 16 01-09 22:32:56.854 6900-6900/cc.lijingbo.pattern_observer E/FordCar: FordCar,绿灯,行驶
2. 当点击按钮-自由通过(取消注册),这个时候点击红绿灯按钮不起作用,不打印日志
参考:
《对象间的联动——观察者模式》:http://blog.csdn.net/lovelion/article/details/7720232
《面试被问设计模式?不要怕看这里:观察者模式》:http://mp.weixin.qq.com/s/pH7ifcOPzVxdrAIk4W8HiQ
《设计模式之观察者模式》:http://www.jianshu.com/p/d55ee6e83d66#