Java设计模式之——观察者模式(Observer)

本文通过一个生动的例子介绍了观察者模式的实现方式。该模式定义了对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

年底了,手头上的项目已经处于收尾阶段,没什么新任务。这段时间争取写两三篇关于设计模式的文章,便于自己加深理解。先从观察者模式开始写起。

一、例子

公司开发讨论组,基本上每天斗图,大部分图片让人看着血脉偾张,眼睛离不开,都是漂亮的美女图,是一种不错的休息方式。

考虑一种场景,大学校园里,男生们想知道他们女神的动态,但又不可能对女神随时随地尾随不去,穷跟不舍。怎么办,买通她闺蜜(给钱,请吃饭,让她占便宜等等)。女神一有新情况,闺蜜就把相关消息透露给感兴趣的男生。暂定闺蜜只把女神在宿舍的动态往外透露,比如女神回到宿舍了,在洗澡,在和某某男生视频聊天,在看电影等等。

下面用代码实现这种场景,先定义女神的接口:

//女神的接口,定义了三个事件,回到宿舍、洗澡、看电影
public interface IGoddess {
    //回到宿舍
    void backToDormitory();

    //洗澡
    void haveAShower();

    //看电影
    void watchMoive();
}

接着再定义闺蜜的接口,闺蜜需要做两件事,一是收集女神的信息,二是把收集的信息透露给给了自己好处的男生。男生可能会有多个,每个男生都需要通知到,对于男生来说,女神的闺蜜就是他们的观察对象,女神不能直接观察到,只能通过观察她闺蜜,间接观察到女神的动态。这里把闺蜜收集信息和把收集的信息透露给相关男生分成两个接口:

//闺蜜的接口一,收集女神信息的接口
public interface IFemaleFriend {
    //收集女神的信息
    void gatherInfo(String content);
}

把收集的信息透露给相关男生的接口等一下再定义,先定义男生的接口。相对于女神的闺蜜来说,男生是她的观察者,她是一个被观察者。当闺蜜把消息放出去的时候,接收到消息的男生就会采取相应行动,这里把男生的接口名定为观察者(observer):

//男生的接口,观察者接口
public interface Observer {
    //收到消息后采取相应行动
    void takeAction(String content);
}

接下来再定义女神闺蜜把消息透露给男生的接口,后续可能会有更多男生需要她透露女神的消息,她需要把这些给了好处的男生加入自己的名单中,将消息一一通知给他们,也有些男生不给好处了,她就把他们从名单中删除,否则自己利益受损。这里将这个接口定义为一个被观察者接口:

//闺蜜的接口二,透露消息的接口,被观察者接口
public interface Observable {
    //给了好处的男生需要加入名单
    void addObserver(Observer observer);
    //不再给好处的男生需要剔除
    void deleteObserver(Observer observer);
    //将消息透露给在名单中的男生
    void notifyObservers(String content);
}

接口已经定义好,接下来实现女神一号,女神一号的闺蜜如花,希望得到女神动态的男生一号和男生二号的具体类。首先是女神的具体实现类,女神一号:

//女神实现类,名字为女神一号
public class GoddessNumOne implements IGoddess {

    private IFemaleFriend femaleFriend;

    public GoddessNumOne(IFemaleFriend femaleFriend){
        this.femaleFriend = femaleFriend;
    }

    @Override
    public void backToDormitory() {
        System.out.println();
        System.out.println("女神一号:回到宿舍了");
        //身边闺蜜收集信息
        femaleFriend.gatherInfo("回到宿舍");
    }

    @Override
    public void haveAShower() {
        System.out.println();
        System.out.println("女神一号:在洗澡了");
        //身边闺蜜收集信息
        femaleFriend.gatherInfo("在洗澡");
    }

    @Override
    public void watchMoive() {
        System.out.println();
        System.out.println("女神一号:在看电影了");
        //身边闺蜜收集信息
        femaleFriend.gatherInfo("在看电影");
    }
}

接着看闺蜜如花的具体实现类:

public class RuHua implements Observable, IFemaleFriend{
    private ArrayList<Observer> observersList = new ArrayList<>();

    @Override
    public void gatherInfo(String content) {
        //一收到消息就将消息透露给,给了自己好处的男生
        notifyObservers(content);
    }

    @Override
    public void addObserver(Observer observer) {
        //只要男生给了好处,都加入名单
        observersList.add(observer);
    }

    @Override
    public void deleteObserver(Observer observer) {
        //不给好处就从名单中踢出
        observersList.remove(observer);
    }

    @Override
    public void notifyObservers(String content) {
        //把消息通知给在名单中的男生
        for (Observer observer : observersList) {
            observer.takeAction(content);
        }
    }
}

接下来看观察者(男生)的两个具体实现类,男生一号和男生二号:

//男生一
public class CollegeBoyOne implements Observer{

    @Override
    public void takeAction(String content) {
        if (content.equals("回到宿舍")) {
            System.out.println("男生一:好,很好,非常好!");
        } else if (content.equals("在洗澡")) {
            System.out.println("男生一:啊!受不了了,老子要打灰机了!");
        } else if (content.equals("在看电影")) {
            System.out.println("男生一:不会是在看精华片吧,嘿嘿!");
        }   
    }
}
//男生二
public class CollegeBoyTwo implements Observer{

    @Override
    public void takeAction(String content) {
        if (content.equals("回到宿舍")) {
            System.out.println("男生二:嗯嗯");
        } else if (content.equals("在洗澡")) {
            System.out.println("男生二:嘿嘿嘿嘿嘿嘿嘿!");
        } else if (content.equals("在看电影")) {
            System.out.println("男生二:看什么电影呢,改天我也看看。");
        }
    }
}

接下来看场景类,把所有这些联系起来:

public class Client {

    public static void main(String[] args) {
        //如花出场
        RuHua ruHua = new RuHua();
        //男生一出场
        Observer collegeBoyOne = new CollegeBoyOne();
        //男生二出场
        Observer collegeBoyTwo = new CollegeBoyTwo();
        //把男生一加入如花的名单
        ruHua.addObserver(collegeBoyOne);
        //把男生二加入如花的名单
        ruHua.addObserver(collegeBoyTwo);
        //女神出场,通过构造器把闺蜜如花传入
        IGoddess goddessNumOne = new GoddessNumOne(ruHua);
        //女神回到宿舍
        goddessNumOne.backToDormitory();
        //女神在洗澡
        goddessNumOne.haveAShower();
        //女神在看电影
        goddessNumOne.watchMoive();
    }

}

运行结果如下:

女神一号:回到宿舍了
男生一:好,很好,非常好!
男生二:嗯嗯

女神一号:在洗澡了
男生一:啊!受不了了,老子要打灰机了!
男生二:嘿嘿嘿嘿嘿嘿嘿!

女神一号:在看电影了
男生一:不会是在看精华片吧,嘿嘿!
男生二:看什么电影呢,改天我也看看。

二、观察者模式

上面就是一个观察者模式的例子。

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

观察者模式提供了一种对象设计,让被观察者(上面例子中的如花)和观察者(上面例子中的男生一号和二号)之间松耦合。

关于观察者的一切,被观察者(如花)只知道观察者(男生)实现了某个接口,被观察者(如花)不需要知道观察者(男生)的具体类是谁、做了什么或其他任何细节。只要男生给如花好处了,不管如花认不认识那个男生,如花都会给他提供女神的相关信息。

任何时候都可以给被观察者(如花)增加新的观察者(男生)。被观察者唯一依赖的东西是一个实现了Observer接口的列表。在运行时可以用新的观察者取代现有的观察者,被观察者不会受到任何影响。也可以在任何时候删除某些观察者。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值