设计模式之观察者模式

  红色警戒--间谍

  间谍是个神奇的角色,可以偷到敌人的矿厂、军营、坦克厂。偷到敌人军营的时,所有的一级兵都能升级成二级,爽歪了。

  所以跟哥们打仗的时候就使劲造狗,狗能识别出间谍,主动出击。

  有时忘了造狗,眼瞅着敌人的间谍大摇大摆地进入军营,着实郁闷。

  间谍进入军营做了什么呢?

  假设现在有一个两级的美国大兵、一个伞兵那这个间谍应该怎么做呢。

    public void interAnBarracks(){
        System.out.println("间谍进入了军营");
        footSolider1.partrol();
        footSolider2.partrol();
        liberationArmy1.partrol();
    }

  傻子都能看出来,这有问题啊,如果间谍进入军营之前有早出一个兵来怎么办?改代码么?

  显然不行。

  那我在间谍这里维护一个SoliderList   然后游戏中维护这个List,新造出一个兵来就加入到List中,兵升级了就从List中移除,怎么样?

  累不累啊,游戏要时刻关心着当前有多少兵,有一个兵升级了,就赶紧去移除一下。真是操碎了心啊。

  那到底该怎么办呢,别急,我们先把观察者模式的概念提出来。

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

  观察者模式的目的是提供一种对象设计,让主题和观察者之间松耦合,使得对象之间的互相依赖降到最低。

  这又是一条设计原则:

找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起。

   现在我们得出设计方法:在间谍那里维护一份名单,大兵可以注册进这个名单(新来的大兵),也可以从名单中申请退出(大兵升级了)。间谍偷兵营成功后,就通知名单的人,让他们升级。

package com.zzl.designpattern.strategy;

import com.zzl.designpattern.observer.Sky;

public abstract class Solider {
    /**
    * 行为类
    */
    IFireable fireable;

    /**
     * 间谍
     */
    Sky sky;
    
    /**
    * 冲刺
    */
    public void rush(String direction){
        System.out.println("向 " + direction + " 冲刺");

    }
    /**
     * 从间谍那里除名
     */
    public void unregisteSelf(){
        sky.removeSolider(this);
    }
    /**
    * 升级
    */
    public abstract void  partrol();
    /**
    * 开火
    */
    public void fire(){
        fireable.fire();
    }
    /**
    * setFireable
    */
    public void setFireable(IFireable fireable){
        this.fireable = fireable;
    }
    
    public Sky getSky() {
        return sky;
    }
    public void setSky(Sky sky) {
        this.sky = sky;
    }
    
}
Solider.java
package com.zzl.designpattern.strategy;

import com.zzl.designpattern.observer.Sky;

public class FootSolider extends Solider {

    public FootSolider(Sky sky){
        
        fireable = new FireWithGun();
        System.out.println("新建一个一级美国大兵");
        this.sky = sky;
        sky.registerSolider(this);
    }

    @Override
    public void partrol() {
        System.out.println("美国大兵升级了!");
        this.setFireable(new FireWithAK47());
        unregisteSelf();
    }

}
FootSolider.java
package com.zzl.designpattern.strategy;

import com.zzl.designpattern.observer.Sky;

public class LiberationArmy extends Solider {

    public LiberationArmy(Sky sky){
        fireable = new FireWithGun();
        System.out.println("新建一个一级伞兵");
        this.sky = sky;
        sky.registerSolider(this);
    }
    @Override
    public void partrol() {
        System.out.println("伞兵升级了!");
        this.setFireable(new FireWithAK47());
        unregisteSelf();

    }
    
    
    

}
LiberationArmy.java
package com.zzl.designpattern.observer;

import java.util.ArrayList;
import java.util.List;

import com.zzl.designpattern.strategy.Solider;

public class Sky {
    private List<Solider> soliderList;
    public Sky(){
        soliderList = new ArrayList<Solider>();
        System.out.println("新建一个间谍");
    }
    
    public void interAnBarracks(){
        System.out.println("间谍进入了军营");
        notifyObservers();
    }
    public void notifyObservers(){
        for(Solider solider : soliderList){
            solider.partrol();
        }
    }
    
    public void registerSolider(Solider solider){
        soliderList.add(solider);
        System.out.println("间谍的名单中新增了一名大兵");
    }
    
    public void removeSolider(Solider solider){
        int i = soliderList.indexOf(solider);
        if(i > 0){
            soliderList.remove(i);
            System.out.println("间谍的名单中移除了一名大兵");
        }
    }
    
}
Sky.java
package com.zzl.designpattern.main;

import com.zzl.designpattern.observer.Sky;
import com.zzl.designpattern.strategy.FootSolider;
import com.zzl.designpattern.strategy.LiberationArmy;
import com.zzl.designpattern.strategy.Solider;

public class Game {

    public static void main(String[] args) {
        Sky sky = new Sky();
        Solider footSolider1 = new FootSolider(sky);
        Solider footSolider2 = new FootSolider(sky);
        Solider liberationArmy1 = new LiberationArmy(sky);
        Solider liberationArmy2 = new LiberationArmy(sky);
        liberationArmy2.fire();
        liberationArmy2.partrol();
        liberationArmy2.fire();
        sky.interAnBarracks();
        footSolider1.fire();
        footSolider2.fire();
        liberationArmy1.fire();
        
    }

}
Game.java

   故事是这样的,美国大兵1、美国大兵2走出兵营,伞兵1、伞兵2也都从天而降,他们出来的时候都在间谍那里注册了名字,伞兵2运气比较好,出来以后打死了一个敌人,于是荣升为二级兵,于是换了AK47,就从间谍那退出名单了。这会儿间谍偷了对方的兵营,于是全民狂欢,一级兵都升级为二级兵用上了AK47了,也都从间谍那除名了。输出是这样的:

新建一个间谍
新建一个一级美国大兵
间谍的名单中新增了一名大兵
新建一个一级美国大兵
间谍的名单中新增了一名大兵
新建一个一级伞兵
间谍的名单中新增了一名大兵
新建一个一级伞兵
间谍的名单中新增了一名大兵
使用普通枪攻击
伞兵升级了!
间谍的名单中移除了一名大兵
使用AK47攻击!
间谍进入了军营
美国大兵升级了!
美国大兵升级了!
间谍的名单中移除了一名大兵
使用AK47攻击!
使用AK47攻击!
使用普通枪攻击
result

   

  在JDK库中提供了一个观察者模式的内置支持,java.utl包中的Observer接口和Observable类,遗憾的是,被观察者是个抽象类,我们的间谍只能继承这个类,那就不能继承别的类了,那么根据我们的设计原则优先用组合怎么样呢,也不行,因为Observable将关键的方法保护起来了,别人用不着。那我们就只能自己实现这个模式了。有兴趣的可以去看看这两了支持类的源码。

  

原文地址:https://www.cnblogs.com/liangflying521/p/5015607.html