[学习笔记]设计模式[1]-{观察者模式}

来源:互联网 发布:屏幕文字识别软件 编辑:程序博客网 时间:2024/05/16 18:53

设计原则

为了交互对象之间的松耦合设计而努力

松耦合是让对象之间互相依赖的程度降低。松耦合的设计可以让我们的系统更有弹性,能够应对未来的需求变化。

设计模式

观察者模式

观察者模式定义了对象之间的一种一对多的依赖关系。使用这种设计模式,可以当一个对象的状态有改变时,对应所有的依赖者都会收到通知并自动的更新。
还是看一下书上的例子:
气象站有两个布告板,如果获取的气象数据有变化,就需要同步到这两个布告板上。在没有使用观察者模式进行设计的时候,气象站和布告板的代码逻辑如下:

public class 气象站{    public void change(){        double temp = getTemp();        double pressure = getPressure();        //下面是同步变化的方法        布告板1.update(temp,pressure);        布告板2.update(temp,pressure);    }    //其他方法}
public class 布告板{    private double temp;    private double pressure;    public void update(double temp,double pressure){        this.temp = temp;        this.pressure = pressure;        updateDisplay();//更新对外的显示    }    //其他方法}

这样的设计会导致两个问题:
1.布告板的更新是写死在气象站更新的方法里的,如果需要增加新的布告板或者删除原有的布告板,就需要对原有的代码进行侵入修改。
2.如果有新的布告板,需要的变量字段不再是原有的字段,比如新增一个humidity字段,就需要对原有的类进行修改。
下面针对这两个问题进行解决:
1.使用观察者模式,将气象站作为主题,布告板作为订阅者。订阅者把自己添加到主题的订阅列表中,由主题进行统一的update
首先,实现一个订阅者的接口类。

public interface Observer{    public void update(double temp,double pressure);}

主题的接口:

public interface Subject{    public void addObserver(Observer o);    //添加订阅类    public void removeObserver(Observer o); //删除订阅类    public void notifyAllObserver();    //通知所有订阅的类}

现在的气象站是这样的:

public class 气象站 implements Subject{    private List<Observer> observers;    public void addObserver(Observer o){        observers.add(o);    }    public void removeObserver(Observer o){        int i = observers.indexOf(o);        if(i >= 0){            observers.remove(i);        }    }    public void notifyAllObserver(){        for(Observer o : observers){            o.update(this.temp, this.pressure);        }    }}

新的布告板是这样的:

public class 布告板1 implements Observer{    private double temp;    private double pressure;    private Subject subject;    public 布告板(Subject subject){        this.subject = subject;        subject.addObserver(this);    }    public void update(double temp,double pressure){        this.temp = temp;        this.pressure = pressure;        updateDisplay();//更新对外的显示    }    public void stopUpdate(){        subject.removeObserver(this);    }    //其他方法}

通过这样的设计就可以使订阅气象站的布告板可以灵活地增删了。
但是还遗留了一个问题,就是如果气象站对外发布的信息增加或减少了怎么办。下面是解决第二点问题的方法:
2.还记得上一章的策略模式嘛?如果气象站对外发布的信息会变动,就把它抽象出来!
新增一个气象信息的类,把需要的信息都包装起来.下面是添加字段后更改的结果:

public class WeatherInfo{    private double temp;    private double pressure;    private double humidity;    //get set方法}

新的气象站会把WeatherInfo类通知给各个布告板:

public class 气象站 implements Subject{    private List<Observer> observers;    public void addObserver(Observer o){        observers.add(o);    }    public void removeObserver(Observer o){        int i = observers.indexOf(o);        if(i >= 0){            observers.remove(i);        }    }    public void notifyAllObserver(){        weatherInfo.setTemp(this.temp);        weatherInfo.setPressure(this.pressure);        weatherInfo.setHumidity(this.humidity);        for(Observer o : observers){            o.update(this.weatherInfo);        }    }}

下面是三个不同的布告板,为方便简洁,只写出不同的代码:

public class 布告板1 implements Observer{    //其他方法    public void update(WeatherInfo weatherInfo){        this.temp = weatherInfo.getTemp();        this.pressure = weatherInfo.getPressure();        updateDisplay();//更新对外的显示    }    //其他方法}
public class 布告板2 implements Observer{    //其他方法    public void update(WeatherInfo weatherInfo){        this.temp = weatherInfo.getTemp();        this.pressure = weatherInfo.getPressure();        this.humidity = weatherInfo.getHumidity();        updateDisplay();//更新对外的显示    }    //其他方法}

通过这种方法就可以对整个系统松耦合的设计了。

0 0
原创粉丝点击