zoukankan      html  css  js  c++  java
  • 设计模式-观察者模式(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#

  • 相关阅读:
    告别零码软件
    win+mingw+libxml2试用笔记
    beacon with java 1.7 on fedora
    mininet指令详解
    java Socket完美实例
    gnome3 下 qt 应用极其丑陋的解决方案
    org.apache.log4j Class Level
    Mac如何修改文本文件编码
    unity性能优化相关
    平面图判定
  • 原文地址:https://www.cnblogs.com/liyiran/p/6298346.html
Copyright © 2011-2022 走看看