设计模式—观察者模式

本文详细解释了观察者模式,涉及核心角色(Subject和Observer)、工作原理、优点(解耦、可扩展性和易于维护)以及与发布-订阅模式的区别。还通过Java代码示例展示了如何实现和应用观察者模式。
摘要由CSDN通过智能技术生成

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。

在观察者模式中,有两个核心角色:

  1. Subject(主题):也称为被观察者或可观察对象,它是具有状态的对象,当其状态发生变化时,会通知所有的观察者。

  2. Observer(观察者):也称为订阅者或观察者,它定义了一个接口,用于接收主题的通知,并进行相应的处理。

观察者模式的工作原理如下:

  1. 主题维护一个观察者列表,用于存储所有订阅该主题的观察者。

  2. 当主题的状态发生变化时,会遍历观察者列表,依次调用每个观察者的更新方法。

  3. 观察者收到通知后,根据主题的状态进行相应的处理。

观察者模式的优点包括:

  • 解耦性:主题和观察者之间是松耦合的,它们可以独立地进行扩展和修改,互不影响。

  • 可扩展性:可以方便地增加新的观察者,以及在不修改主题代码的情况下增加新的主题。

  • 易于维护:由于主题和观察者之间的关系是明确的,代码的维护和调试相对容易。

举个例子:被观察者=新闻,观察者有“播放新闻”和“打印新闻”,当有新的新闻产生时,立刻播放和打印新闻。(建议尽量面向抽象编程、接口编程)

先定义观察者和被观察者的抽象类。

/**
 * 观察者抽象
 */
public abstract class Observer {

    /**
     * 处理新闻内容
     * @param msg
     */
    public abstract void handle(String msg);

    /**
     * 观察者的身份
     * @return
     */
    public abstract String identity();
}
/**
 * 被观察者抽象
 */
public abstract class Subject {

    /**
     * 观察者列表
     */
    public List<Observer> observerList;

    /**
     * 加入观察者
     * @param observer
     */
    public abstract void register(Observer observer);

    /**
     * 剔除观察者
     * @param observer
     */
    public abstract void cancel(Observer observer);

    /**
     * 通知内容
     * @param msg
     */
    public abstract void notice(String msg);
}

再定义新闻类,继承了被观察者抽象类,表示自己是某个具有实际业务含义的被观察者。

public class News extends Subject {

    public News() {
        this.observerList = new ArrayList<>();
    }

    @Override
    public void register(Observer observer) {
        this.observerList.add(observer);
    }

    @Override
    public void cancel(Observer observer) {
        for (Observer ob : this.observerList) {
            if (ob.identity().equals(observer.identity())) {
                this.observerList.remove(ob);
            }
        }
    }

    @Override
    public void notice(String msg) {
        for (Observer ob : this.observerList) {
            ob.handle(msg);
        }
    }
}

定义播放新闻类和打印新闻类,表示具体的观察者。

public class PlayNews extends Observer {

    Logger logger = LoggerFactory.getLogger(PlayNews.class);

    @Override
    public void handle(String msg) {
        logger.info("播放新闻:{}", msg);
    }

    @Override
    public String identity() {
        return "play";
    }
}


public class PrintNews extends Observer {

    Logger logger = LoggerFactory.getLogger(PrintNews.class);

    @Override
    public void handle(String msg) {
        logger.info("打印新闻:{}", msg);
    }

    @Override
    public String identity() {
        return "print";
    }
}

测试一下:

public class Test {

    public static void main(String[] args) {
        News news = new News();
        PlayNews playNews = new PlayNews();
        PrintNews printNews = new PrintNews();
        news.register(playNews);
        news.register(printNews);
        news.notice("油价微涨1元");

        news.cancel(playNews);
        news.notice("油价暴跌1分");
    }
}

个人理解:

1、观察者模式类似于发布-订阅,需要被观察者发出信息让观察者去处理,但是又与发布-订阅模式不同,观察者与被观察者是直接联系,互相有感知,中间没有第三方角色存在,而发布-订阅模式中,发布者与订阅者之间有第三方角色存在,比如kafka中,生产者发送消息到 topic,消费者从topic获取消息,而不是生产者直接发消息给消费者,更多地是体现发布者与订阅者之间的相互无感知,解耦,以及异步机制。

2、观察者模式的亮点在于它的“加入观察者”、“剔除观察者”思想,适合那些观察者随时可变的场景,否则就没什么特点可言了,还不如策略模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值