您当前的位置:首页 > 计算机 > 编程开发 > 设计模式

【设计模式】20.行为型模式-观察者(Observer)

时间:02-01来源:作者:点击数:

一、描述

  定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。也称为发布-订阅模式。

  角色:

  1.抽象目标类:除自身业务逻辑外,包含增加、删除、唤醒观察者功能。

  2.具体目标类:为那些在目标发生改变时需获取通知的对象定义一个更新接口。

  2.抽象观察类:定义响应抽象方法。

  3.具体观察类:继承抽象观察类,实现抽象方法。

  类图:

二、优点

  1.目标和观察者之间的耦合是最小的。一个目标所知道的仅仅是它有一系列的观察者,但是不知道这些观察者是哪些类,目标类只需要负责通知就可以了。

  2.支持广播通信。通知被自动广播给所有已向该目标对象登记的有关对象。

三、缺点

  1.意外的更新。因为一个观察者并不知道其他观察者的存在,它可能对改变目标的最终代价一无所知。

  2.如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会话费很多的时间。

  3.如果观察者和观察目标之间有循环依赖的话,观察目标会触发他们之间进行循环调用,可能导致系统崩溃。

四、适用场景

  1.当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变

  2.当一个对象必须通知其他对象,而它又不能假定其他对象是谁。

五、示例

  以“交通灯亮,其他对象针对交通灯不同的颜色作出不同反应为例”。

  1.抽象观察者类

public abstract class AbstractObserver {
    /**
     * 作出反应
     *
     * @param type
     */
    abstract void update(Integer type);
}

  2.具体观察者类,汽车、行人、自行车等

  (1)汽车

public class CarObserver extends AbstractObserver {
    @Override
    void update(Integer type) {
        System.out.print("我是轿车:");
        if (Objects.equal(type, 1)) {
            System.out.println("踩刹车,停车");
        } else if (Objects.equal(type, 2)) {
            System.out.println("开始行驶");
        } else if (Objects.equal(type, 3)) {
            System.out.println("缓慢行驶");
        }
    }
}

  (2)行人

public class PedestriansObserver extends AbstractObserver {
    @Override
    void update(Integer type) {
        System.out.print("我是行人:");
        if (Objects.equal(type, 1)) {
            System.out.println("原地站立");
        } else if (Objects.equal(type, 2)) {
            System.out.println("行走");
        } else if (Objects.equal(type, 3)) {
            System.out.println("行走,注意车辆");
        }
    }
}

  (3)自行车

public class BikeObserver extends AbstractObserver {
    @Override
    void update(Integer type) {
        System.out.print("我是自行车:");
        if (Objects.equal(type, 1)) {
            System.out.println("捏闸,停车");
        } else if (Objects.equal(type, 2)) {
            System.out.println("开始骑行");
        } else if (Objects.equal(type, 3)) {
            System.out.println("骑行,注意车辆");
        }
    }
}

  3.抽象目标类

public abstract class AbstractSubject {
    public List<AbstractObserver> observerList = new ArrayList<>();

    public void addObservers(AbstractObserver observer) {
        observerList.add(observer);
    }

    public void removeObserver(AbstractObserver observer) {
        observerList.remove(observer);
    }

    /**
     * 当前目标的行为
     *
     * @param type
     */
    public abstract void doAction(Integer type);
}

  4.具体目标类,交通灯类

public class TrafficFlightSubject extends AbstractSubject {
    @Override
    public void doAction(Integer type) {
        if (Objects.equal(type, 1)) {
            System.out.println("红灯亮");
        } else if (Objects.equal(type, 2)) {
            System.out.println("绿灯亮");
        } else if (Objects.equal(type, 3)) {
            System.out.println("黄灯亮");
        }
        for (AbstractObserver observer : observerList) {
            observer.update(type);
        }
    }
}

  5.测试类

public class Client {
    public static void main(String[] args) {
        TrafficFlightSubject subject = new TrafficFlightSubject();

        CarObserver carObserver = new CarObserver();
        subject.addObservers(carObserver);

        PedestriansObserver pedestriansObserver = new PedestriansObserver();
        subject.addObservers(pedestriansObserver);

        BikeObserver bikeObserver = new BikeObserver();
        subject.addObservers(bikeObserver);
        
        //红灯
        subject.doAction(1);
        System.out.println();
        
        //绿灯
        subject.doAction(2);
        System.out.println();
        
        //黄灯
        subject.doAction(3);
    }
}

  测试效果:

六、注意事项

  观察者和中介者模式有些类似,但是不要弄混。二者的区别如下:

  1.行为不同,观察者模式的目标类自身会有操作,之后通知观察者列表。中介者模式是直接通知对应的对象。

  2.目的不同,观察者模式主要是一堆观察者观察目标类,当目标类有所操作之后,同时作出反应。中介者模式是一个对象通过中介通知另外一个对象。

  3.目标群体不同,观察者模式中,目标类并不清楚观察者列表具体包含哪些对象;中介者模式的通知模式是清楚要通知哪些对象的。

  推荐一篇解释二者对比比较透彻的文章:https://www.cdsy.xyz/computer/programme/design_pattern/230201/cd40017.html

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门