观察者设计模式

观察者设计模式:又被称作是发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个对象的状态发生变化时,会通知所有的观察者对象,使他们能够自动更新自己。

这里写图片描述

解决的问题:将系统分割成一些类或者相互协作的类,会有一个不好的副作用。那就是需要维护相关对象的一致性。我们不希望为了维护一致性而使得各种类紧密耦合,这样会给维护扩展重用都带来不便。观察者就是解决这一类问题的。

典型的观察者设计模式(双向耦合)

Secretary.java-通知类

public class Secretary {

    //同事列表
    private List<StockObserver> observers=new ArrayList<StockObserver>();
    private String action;

    //增加
    public void attach(StockObserver observer){
        observers.add(observer);
    }

    public void inform(){
        for(StockObserver s:observers){
            s.update();
        }
    }
    //前台状态
    public String SecretaryAction;
    public String getSecretaryAction() {
        return SecretaryAction;
    }
    public void setSecretaryAction(String secretaryAction) {
        SecretaryAction = secretaryAction;
    }
}

StockObserver.java-订阅类

public class StockObserver {

    private String name;
    private Secretary sub;

    public StockObserver(String name,Secretary sub){
        this.name=name;
        this.sub=sub;
    }

    public void update() {
        System.out.println(sub.SecretaryAction+" "+name+" 关闭股票行情,继续努力工作");
    }

}

测试

public class Test {
    public static void main(String[] args) {
        //前台
        Secretary secretary = new Secretary();
        //看股票的同事
        StockObserver stockObserver1 = new StockObserver("张三",secretary);
        StockObserver stockObserver2 = new StockObserver("李四",secretary);

        //前台记录下两位同事
        secretary.attach(stockObserver1);
        secretary.attach(stockObserver2);

        secretary.setSecretaryAction("Boss回来了!!!");
        secretary.inform();
    }
}

输出

典型的观察者设计模式(抽象观察者和订阅者)

Subject.java-抽象通知类

public abstract class Subject {

    abstract void attach(Observer observer);
    abstract void detach(Observer observer);

    abstract void inform();

    protected String subjectState;

    public String getSubjectState() {
        return subjectState;
    }
    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
    }
}

Boss.java-具体通知类

public class Boss extends Subject{

    //同事列表
    //private 只有当前类可以访问
    private List<Observer> observers=new ArrayList<Observer>();
    private String action;

    @Override
    public void attach(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void detach(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void inform() {
        for(Observer o:observers){
            o.update();
        }
    }
}

Observer.java-抽象订阅者

public abstract class Observer {

    //protected 同一个包中可以访问,继承的子类可以访问
    protected String name;
    protected Subject sub;

    public abstract void update();

    public Observer(String name,Subject sub){
        this.name=name;
        this.sub=sub;
    }
}

NBAObserver.java-具体订阅者

public class NBAObserver extends Observer{

    public NBAObserver(String name, Subject sub) {
        super(name, sub);
    }

    @Override
    public void update() {
        System.out.println(sub.getSubjectState()+" "+name+" 关闭NBA直播继续工作!!!");
    }
}

StockObserver.java-具体订阅者

public class StockObserver extends Observer{

    public StockObserver(String name, Subject sub) {
        super(name, sub);
    }

    @Override
    public void update() {
        System.out.println(sub.getSubjectState()+" "+name+" 关闭股票行情继续工作!!!");
    }
}

测试

public class Test {

    public static void main(String[] args) {
        Subject boss = new Boss();

        Observer observer1 = new NBAObserver("张三",boss);
        Observer observer2 = new StockObserver("李四",boss);

        boss.attach(observer1);
        boss.attach(observer2);

        boss.setSubjectState("我胡汉三回来了!");
        boss.inform();

    }
}

输出

观察者设计模式:观察者设计模式解决的问题时当一个对象发生指定的动作时,要通过另外一个对象做出相应的处理。

需求: 编写一个气象站、一个工人两个类,当气象站更新天气 的时候,要通知人做出相应的处理。

问题1: 气象站更新了多次天气,然后人才做一次的处理。

问题2: 目前气象站只能通知一个人而已。

问题3: 在现实生活中出了工人群体要关注天气,其他 的群体也需要关注天气

观察者设计模式的步骤:
1. 当前目前对象发生指定的动作是,要通知另外一个对象做出相应的处理,这时候应该把对方的相应处理方法定义在接口上。
2. 在当前对象维护接口的引用,当当前对象发生指定的动作这时候即可调用接口中的方法了。


//人 是要根据天气做出相应的处理的。
public class Emp implements Weather{

    String name;

    public Emp(String name) {
        this.name = name;
    }


    //人是要根据天气做出相应的处理的。  "晴天","雾霾","刮风","冰雹","下雪"
    public void notifyWeather(String weather){
        if("晴天".equals(weather)){
            System.out.println(name+"高高兴兴的去上班!!");
        }else if("雾霾".equals(weather)){
            System.out.println(name+"戴着消毒面具去上班!");
        }else if("刮风".equals(weather)){
            System.out.println(name+"拖着大石头过来上班!");
        }else if("冰雹".equals(weather)){
            System.out.println(name+"戴着头盔过来上班!");
        }else if("下雪".equals(weather)){
            System.out.println(name+"戴着被子过来上班!");
        }


    }

}

public class Student implements Weather{

    String name;

    public Student(String name) {
        super();
        this.name = name;
    }


    public void notifyWeather(String weather){
        if("晴天".equals(weather)){
            System.out.println(name+"高高兴兴的去开学!!");
        }else if("雾霾".equals(weather)){
            System.out.println(name+"吸多两口去上学!");
        }else if("刮风".equals(weather)){
            System.out.println(name+"在家睡觉!");
        }else if("冰雹".equals(weather)){
            System.out.println(name+"在家睡觉!");
        }else if("下雪".equals(weather)){
            System.out.println(name+"等下完再去上学!");
        }


    }

}
//订阅天气预报的接口
public interface Weather {
    public void notifyWeather(String weather);

}
//气象站
public class WeatherStation {

    String[] weathers = {"晴天","雾霾","刮风","冰雹","下雪"};

    //当前天气
    String  weather ;

    //该集合中存储的都是需要收听天气预报的人
    ArrayList<Weather> list = new ArrayList<Weather>();  //程序设计讲究低耦合---->尽量不要让一个类过分依赖于另外一个类。



    public void addListener(Weather e){
        list.add(e);
    }


    //开始工作
    public void startWork() {
        final Random random = new Random();

        new Thread(){   
            @Override
            public void run() {
                while(true){ 
                    updateWeather(); // 每1~1.5秒更新一次天气  1000~1500
                    for(Weather e : list){
                        e.notifyWeather(weather);
                    }

                    int  s = random.nextInt(501)+1000; //  500
                    try {
                        Thread.sleep(s);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }               
            }

        }.start();

    }



    //更新天气的 方法
    public void updateWeather(){
        Random random = new Random();
        int index = random.nextInt(weathers.length);
        weather = weathers[index];
        System.out.println("当前的天气是: " + weather);
    }

}

public class WeatherMain {

    public static void main(String[] args) throws Exception {
        //工人
        Emp e = new Emp("小明");
        Emp e2 = new Emp("如花");

        //学生
        Student s1 = new Student("狗娃");
        Student s2 = new Student("狗剩");


        WeatherStation station = new WeatherStation();
        station.addListener(e);
        station.addListener(e2);
        station.addListener(s1);
        station.addListener(s2);

        station.startWork();
    }

}

观察者模式多用于实现订阅功能的场景,例如微博的订阅,当我们订阅了某个人的微博账号,当这个人发布了新的消息,就会通知我们。

源码:https://github.com/zxiang179/DesignPattern

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值