it程序员

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

2017-08-26  本文已影响83人  阿菜的博客
观察者模式

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

一:模式理解

  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包中有观察者模式的实现。
  1. Java util自带Observable是个类,主题继承这个类,就不能再继承其他类,不利于扩展。
  2. 观察者模式中,主题拥有一个观察者列表,观察者又引用了主题。
上一篇 下一篇

猜你喜欢

热点阅读