漫画:设计模式中的 “观察者模式”

漫画:设计模式中的 “观察者模式”_第1张图片

漫画:设计模式中的 “观察者模式”_第2张图片

—————  第二天  —————

漫画:设计模式中的 “观察者模式”_第3张图片

漫画:设计模式中的 “观察者模式”_第4张图片

漫画:设计模式中的 “观察者模式”_第5张图片

漫画:设计模式中的 “观察者模式”_第6张图片

漫画:设计模式中的 “观察者模式”_第7张图片

————————————

漫画:设计模式中的 “观察者模式”_第8张图片

漫画:设计模式中的 “观察者模式”_第9张图片

漫画:设计模式中的 “观察者模式”_第10张图片

漫画:设计模式中的 “观察者模式”_第11张图片

漫画:设计模式中的 “观察者模式”_第12张图片

场景1:游戏操作界面

在一个小游戏中,包含一个简单的操作界面,界面上有两个按钮:道具和魔法。

漫画:设计模式中的 “观察者模式”_第13张图片

如果点击“道具”按钮,游戏里的主角会使用道具;如果点击“魔法”按钮,游戏里的主角会使用魔法。

漫画:设计模式中的 “观察者模式”_第14张图片

如何让主角实时接收到点击按钮的事件,并做出相应的行动呢?

场景2:游戏迷宫

同样在这个小游戏里,有一个迷宫,迷宫里有怪物、陷阱和宝物。

漫画:设计模式中的 “观察者模式”_第15张图片

一旦主角移动到怪物的有效范围,怪物会袭击主角;主角移动到陷阱的有效范围,陷阱会困住主角;主角移动到宝物的有效范围,宝物会为主角加血。

漫画:设计模式中的 “观察者模式”_第16张图片

如何让主角移动的事件被怪物、陷阱、道具感知到,并做出正确的反应?

漫画:设计模式中的 “观察者模式”_第17张图片

漫画:设计模式中的 “观察者模式”_第18张图片

漫画:设计模式中的 “观察者模式”_第19张图片

漫画:设计模式中的 “观察者模式”_第20张图片

漫画:设计模式中的 “观察者模式”_第21张图片

漫画:设计模式中的 “观察者模式”_第22张图片

漫画:设计模式中的 “观察者模式”_第23张图片

漫画:设计模式中的 “观察者模式”_第24张图片

漫画:设计模式中的 “观察者模式”_第25张图片

public class Hero {
    //怪物
    Monster monster;
    //陷阱
    Trap trap;
    //宝物
    Treasure treasure;

    public void move(){
        System.out.println("主角向前移动");
        //主角移动时,分别通知怪物、陷阱和宝物对象
        monster.update();
        trap.update();
        treasure.update();
    }
}

漫画:设计模式中的 “观察者模式”_第26张图片

漫画:设计模式中的 “观察者模式”_第27张图片

漫画:设计模式中的 “观察者模式”_第28张图片

漫画:设计模式中的 “观察者模式”_第29张图片

漫画:设计模式中的 “观察者模式”_第30张图片

漫画:设计模式中的 “观察者模式”_第31张图片

漫画:设计模式中的 “观察者模式”_第32张图片

漫画:设计模式中的 “观察者模式”_第33张图片

漫画:设计模式中的 “观察者模式”_第34张图片

在上面的UML图中,主要有两组实体对象,一组是观察者,一组是被观察者。所有的观察者,都实现了Observer接口;所有的被观察者,都继承自Subject抽象类。

Subject类的成员OberverList,存储着已注册的观察者,当事件发生时,会通知列表中的所有观察者。需要注意的是,OberverList所依赖的是抽象的Observer接口,这样就避免了观察者与被观察者的紧耦合。

漫画:设计模式中的 “观察者模式”_第35张图片

漫画:设计模式中的 “观察者模式”_第36张图片

//观察者
public interface Observer {
    public void update();
}

//被观察者
abstract public class Subject {

    private List observerList = new ArrayList();

    public void attachObserver(Observer observer) {
        observerList.add(observer);
    }

    public void detachObserver(Observer observer){
        observerList.remove(observer);
    }

    public void notifyObservers(){
        for (Observer observer: observerList){
            observer.update();
        }
    }
}

漫画:设计模式中的 “观察者模式”_第37张图片

//怪物
public class Monster implements Observer {

    @Override
    public void update() {
        if(inRange()){
            System.out.println("怪物 对主角攻击!");
        }
    }

    private boolean inRange(){
        //判断主角是否在自己的影响范围内,这里忽略细节,直接返回true
        return true;
    }
}

//陷阱
public class Trap implements Observer {

    @Override
    public void update() {
        if(inRange()){
            System.out.println("陷阱 困住主角!");
        }
    }

    private boolean inRange(){
        //判断主角是否在自己的影响范围内,这里忽略细节,直接返回true
        return true;
    }
}

//宝物
public class Treasure implements Observer {

    @Override
    public void update() {
        if(inRange()){
            System.out.println("宝物 为主角加血!");
        }
    }

    private boolean inRange(){
        //判断主角是否在自己的影响范围内,这里忽略细节,直接返回true
        return true;
    }
}

上面代码中,每一个具体观察者类都实现了update方法,这是事件触发的回调方法,包含了具体观察者对事件的不同反应。

漫画:设计模式中的 “观察者模式”_第38张图片

public class Hero extends Subject{
    void move(){
        System.out.println("主角向前移动");
        notifyObservers();
    }
}


当主角移动时,通知所有已注册的观察者,执行具体观察者各自的update方法。

漫画:设计模式中的 “观察者模式”_第39张图片

public class Client {
    public static void main(String[] args) {
        //初始化对象
        Hero hero = new Hero();
        Monster monster = new Monster();
        Trap trap = new Trap();
        Treasure treasure = new Treasure();
        //注册观察者
        hero.attachObserver(monster);
        hero.attachObserver(trap);
        hero.attachObserver(treasure);
        //移动事件
        hero.move();
    }
}

代码输出如下:

主角向前移动

怪物 对主角攻击!

陷阱 困住主角!

宝物 为主角加血!

漫画:设计模式中的 “观察者模式”_第40张图片

漫画:设计模式中的 “观察者模式”_第41张图片

漫画:设计模式中的 “观察者模式”_第42张图片

漫画:设计模式中的 “观察者模式”_第43张图片

推荐阅读:

还在使用if else写代码?试试 “策略模式” 吧!

喜欢本文的朋友们,欢迎长按下图关注公众号程序员小灰,收看更多精彩内容

给个[在看],是对小灰最大的支持!

你可能感兴趣的:(漫画:设计模式中的 “观察者模式”)