学好设计模式防被祭天:观察者模式

观察者模式

为了防止被“杀”了祭天,学点设计模式,并总结下还是有必要的。

一:模式理解

  1. 观察者模式也可以称为订阅者模式。
  2. 无论是观察者还是订阅者,关注的是主题的变化。
  3. 主题发生某些变化时,需要发生通知给所有的观察者和订阅者。
  4. 观察者和订阅者可以取消对主题的观察或订阅。
  5. 一些对象需要能感知到一个对象变了(做了某些操作)。假设只有一个主题。


二:例子

你家的仆人

你是个富二代,家里有很多仆人。

为了方便,只举例三种,分别是程序员,老司机,女仆。

他们都继承自Servant抽象类,并且都有跪舔的技能,即guitian方法。

public abstract class Servant {

    private FuErDai fuErDai;

    public Servant(FuErDai fuErDai) {
        this.fuErDai = fuErDai;
        fuErDai.addServant(this);
    }

    public void add() {
        fuErDai.addServant(this);
    }

    public void remove() {
        fuErDai.fireServant(this);
    }

    public abstract void guitian();
}
  1. 每个仆人都有一个fuErDai属性,代表心中时刻都有主人。
  2. 并且在构造器中直接把自己作为富二代的仆人。
  3. 富二代比较民主,允许仆人们可以自主决定参加工作或是不干了,分别对应add和remove方法。
  4. 不同仆人跪舔主人的方法不一样,设置为抽象方法。

分别新建程序员,老司机,女仆三个类。

// 程序员
public class Programmer extends Servant {

    public Programmer(FuErDai fuErDai) {
        super(fuErDai);
    }

    @Override
    public void guitian() {
        System.out.println("表演敲代码!");
    }
}

// 老司机
public class Driver extends Servant {
    
    public Driver(FuErDai fuErDai) {
        super(fuErDai);
    }

    @Override
    public void guitian() {
        System.out.println("老司机开个车让富二代开心开心!");
    }
}

// 女仆
public class Maidservant extends Servant {
    
    public Maidservant(FuErDai fuErDai) {
        super(fuErDai);
    }

    @Override
    public void guitian() {
        System.out.println("如果你追到我,我就和你嘿嘿嘿!");
    }
}

作为富二代的你,也有一个对应的类,FuErDai。

public class FuErDai {
    
    private List<Servant> servantList = Lists.newArrayList();
    private int happyIndex;
    private int healthIndex;

    public FuErDai(int happyIndex, int healthIndex) {
        this.happyIndex = happyIndex;
        this.healthIndex = healthIndex;
    }

    public void addServant(Servant servant) {
        int index = servantList.indexOf(servant);
        if (index == -1) {
            servantList.add(servant);
        }
    }

    public void fireServant(Servant servant) {
        int index = servantList.indexOf(servant);
        servantList.remove(index);
    }

    private void notifyServants() {
        for (Servant servant : servantList) {
            servant.guitian();
        }
    }

    public void changeIndex(int happyIndex, int healthIndex) {
        this.happyIndex = happyIndex;
        this.healthIndex = healthIndex;
        notifyServants();
    }
}

你有三个属性,分别是仆人队列,开心指数,健康指数。

有添加仆人和删除仆人的方法。

在没有观察者模式之前,为了防止你不舒服了或是不开心了,仆人们隔三差五都需要来询问一次。

仆人们发现每次走进你房间的时候,你总是对着蓝天白云的电脑桌面发呆。同时,你也觉得很不开心。

有了观察者模式之后,当你的开心指数或者健康指数变化的时候,就会通知每个仆人,即notifyServants,每个仆人都会前来跪舔你。

public class Client {
    public static void main(String[] args) {
        FuErDai fuErDai = new FuErDai(100, 100);
        Programmer programmer = new Programmer(fuErDai);
        Driver driver = new Driver(fuErDai);
        Maidservant maidservant = new Maidservant(fuErDai);
        fuErDai.changeIndex(100, 90);
        System.out.println("--------------");
        programmer.remove();
        fuErDai.changeIndex(100, 80);
    }
}

输入/输出:

表演敲代码!
老司机开个车让富二代开心开心!
如果你追到我,我就和你嘿嘿嘿!


老司机开个车让富二代开心开心!
如果你追到我,我就和你嘿嘿嘿!

可以看到,当你健康指数变化的时候,所有仆人都会前来跪舔。

某天,程序员突然想起之前你答应带他去彻夜鼓掌却一直没再提起,调用了remove方法,不再作为你的仆人。

在你的指数再次变化的时候,程序员将不会来跪舔。


三:再理解

  1. 在例子中,作为富二代的你就是主题,你的仆人们都是观察者/订阅者。
  2. 仆人们再也不用轮询来检查你的变化。
  3. 在通知仆人的方法notifyServants中,可以传参,例子为方便没传递参数。
  4. 在Java util包中有观察者模式的实现。
  • 观察者实现Observer接口,实现update方法;
  • 主题继承Observable类,意思为可被观察,底层用Vector<Observer> obs保存所有的观察者,可做到多线程安全;
  • 在主题变化时,可调用setChanged()和notifyObservers()方法来通知观察者,观察者们执行update()方法;
  • 观察者可通过调用addObserver(this)和deleteObserver(this)方法加入/退出主题的观察者队列。
  1. Java util自带Observable是个类,主题继承这个类,就不能再继承其他类,不利于扩展。
  2. 观察者模式中,主题拥有一个观察者列表,观察者又引用了主题。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容