zoukankan      html  css  js  c++  java
  • 设计模式之观察者模式

      红色警戒--间谍

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

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

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

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

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

        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将关键的方法保护起来了,别人用不着。那我们就只能自己实现这个模式了。有兴趣的可以去看看这两了支持类的源码。

      

  • 相关阅读:
    Leetcode#179 Largest Number
    Leetcode#155 Min Stack
    Leetcode#14 Longest Common Prefix
    Leetcode#101 Symmetric Tree
    Leetcode#172 Fractorial Trailing Zero
    Leetcode#28 Implement strStr()
    Leetcode#46 Permutations
    Leetcode#48 Rotate Image
    Leetcode#134 Gas station
    Leetcode#137 Single Number II
  • 原文地址:https://www.cnblogs.com/liangflying521/p/5015607.html
Copyright © 2011-2022 走看看