zoukankan      html  css  js  c++  java
  • 《Head First 设计模式》之策略模式

    作者:Grey

    原文地址:http://www.cnblogs.com/greyzeng/p/5915202.html

    模式名称

    策略模式(Strategy Pattern)

    需求

    模拟鸭子游戏,游戏中会出现各种鸭子,一边游泳戏水,一边呱呱叫。我们应该如何设计这个鸭子类呢?

    解决方案

    首先,我们可以考虑设计一个鸭子的超类Duck,抽象出鸭子的公共方法,然后其他鸭子类型继承这个超类,对公共方法有自己独有的实现。

    public abstract class Duck {
        
        public abstract void display();
        public abstract void quack(); 
        
        public void swim() {
            System.out.println("all ducks can swim");
        }
        
    }
    
    public class RedHeadDuck extends Duck {
    
        @Override
        public void display() {
            System.out.println("This is RedHeadDuck");
        }
    
        @Override
        public void quack() {
            System.out.println("RedHeadDuck Quack");
        }
    }
    
    public class ModelDuck extends Duck {
        @Override
        public void display() {
            System.out.println("This is ModelDuck");
        }
    
        @Override
        public void quack() {
            System.out.println("ModelDuck Can not Quack");
        }
    }
    

    但是,这种设计,会出现一个问题:
    如果要增加一个可以飞的鸭子,我们在超类中增加一个fly()方法,所有继承这个超类的子类都会有这个方法,导致代码在多个子类中重复。

    public abstract class Duck {
        
        public abstract void display();
        public abstract void quack(); 
        public abstract void fly(); 
        
        public void swim() {
            System.out.println("all ducks can swim");
        }
        
    }
    
    public class RedHeadDuck extends Duck{
    
        @Override
        public void display() {
            System.out.println("This is RedHeadDuck");
        }
    
        @Override
        public void quack() {
            System.out.println("Gua Gua Gua~~");
        }
    
        @Override
        public void fly() {
            System.out.println("fly fly fly~~");
        }
    }
    
    public class ModelDuck extends Duck{
        @Override
        public void display() {
            System.out.println("This is ModelDuck");
        }
    
        @Override
        public void quack() {
            System.out.println("Silence");
        }
    
        @Override
        public void fly() {
            // do nothing
        }
    }
    
    

    更好的一种方法:

    分开变化与不变化的部分,因为Duck类里面fly()quack()会随着鸭子的不同而改变,所以我们需要把这两个行为从Duck里面分离出来,建立一组新类来代表每个行为

    QuackBehavior接口:

    interface QuackBehavior {
        void quack();
    }
    

    QuackBehavior 具体行为:

    public class MuteQuack implements QuackBehavior {
        public void quack() {
            System.out.println("Silence");
        }
    }
    
    public class Gua implements QuackBehavior {
    
        public void quack() {
            System.out.println("Gua Gua Gua~~");
        }
    }
    

    FlyBehavior接口:

    interface FlyBehavior {
        void fly();
    }
    

    FlyBehavior具体行为:

    public class FlyWithWings implements FlyBehavior {
        public void fly() {
            System.out.println("fly fly fly~~~");
        }
    }
    
    public class FlyNoWay implements FlyBehavior {
        public void fly() {
            // do nothing
        }
    }
    

    现在鸭子会将飞行和呱呱叫的动作“委托”给FlyBehaviorQuackBehavior处理,我们在Duck中增加两个方performFly(),performQuack()

    public abstract class Duck {
        Duck() {}
    
        public FlyBehavior flyBehavior;
        public QuackBehavior quackBehavior;
    
        public abstract void display();
    
        public void swim() {
            System.out.println("all ducks can swim");
        }
        public void performFly() {
            flyBehavior.fly();
        }
        public void performQuack() {
            quackBehavior.quack();
        }
    }
    
    

    在每种鸭子继承超类Duck的时候,只需要在构造函数中设置对应的FlyBehaviorQuackBehavior实例变量即可。

    public class RedHeadDuck extends Duck {
        RedHeadDuck() {
            this.quackBehavior = new Gua();
            this.flyBehavior = new FlyWithWings();
        }
    
        @Override
        public void display() {
            System.out.println("This is RedHeadDuck");
        }
        public void performFly() {
            flyBehavior.fly();
        }
        public void performQuack() {
            quackBehavior.quack();
        }
    
    }
    
    public class ModelDuck extends Duck {
        ModelDuck() {
            this.flyBehavior = new FlyNoWay();
            this.quackBehavior = new MuteQuack();
        }
        @Override
        public void display() {
            System.out.println("This is ModelDuck");
        }
        public void performFly() {
            flyBehavior.fly();
        }
        public void performQuack() {
            quackBehavior.quack();
        }
    
    }
    

    同时,我们可以在Duck类中增加对FlyBehaviorQuackBehaviorsetter/getter方法,这样我们就可以动态改变鸭子的行为了

    public abstract class Duck {
        Duck() {}
    
        public FlyBehavior flyBehavior;
        public QuackBehavior quackBehavior;
    
        public abstract void display();
    
        public void swim() {
            System.out.println("all ducks can swim");
        }
        public void performFly() {
            flyBehavior.fly();
        }
        public void performQuack() {
            quackBehavior.quack();
        }
    
        public void setFlyBehavior(FlyBehavior flyBehavior) {
            this.flyBehavior = flyBehavior;
        }
    
        public void setQuackBehavior(QuackBehavior quackBehavior) {
            this.quackBehavior = quackBehavior;
        }
    }
    

    测试代码:

    public class DuckTest {
        public static void main(String[] args) {
            Duck redHeadDuck = new RedHeadDuck();
            redHeadDuck.display();
            redHeadDuck.performFly();
            redHeadDuck.performQuack();
    
            System.out.println();
    
            Duck modelDuck = new ModelDuck();
            modelDuck.display();
            modelDuck.performFly();
            modelDuck.performQuack();
    
            System.out.println();
    
            System.out.println("I want that modelduck can fly");
            modelDuck.setFlyBehavior(new FlyWithWings());
            modelDuck.performFly();
        }
    }
    

    输出结果:

    This is RedHeadDuck
    fly fly fly~~~
    Gua Gua Gua~~
    
    This is ModelDuck
    can not fly
    Silence
    
    I want that modelduck can fly
    fly fly fly~~~
    

    完整代码: Strategy Pattern Source

  • 相关阅读:
    BZOJ.5068.友好的生物(思路)
    BZOJ.4695.最假女选手(线段树 Segment tree Beats!)
    BZOJ.4355.Play with sequence(线段树)
    BZOJ.4909.[SDOI2017]龙与地下城(正态分布 中心极限定理 FFT Simpson积分)
    HDU.4035.Maze(期望DP)
    Codeforces.1027F.Session in BSU(思路 并查集)
    BZOJ.4299.Codechef FRBSUM(主席树)
    UOJ.41.[清华集训2014]矩阵变换(稳定婚姻)
    BZOJ.5312.冒险(线段树)
    UOJ.386.[UNR #3]鸽子固定器(贪心 链表)
  • 原文地址:https://www.cnblogs.com/greyzeng/p/5915202.html
Copyright © 2011-2022 走看看