zoukankan      html  css  js  c++  java
  • 设计模式入门——Head First

    设计模式是被前人发现、经过总结形成了一套某一类问题的一般性解决方案。使用模式最好的方式是:把模式装进脑子,然后在设计和已有的应用中,寻找何处可以使用它们。以往是代码复用,现在是经验复用。

    从模拟鸭子游戏说起

    初始需求:各种鸭子(野鸭MallardDuck、红头鸭RedheadDuck等),一边游泳swim,一边呱呱叫quack,每种鸭子外观都不同display。

    初始方案:设计一个鸭子超类,并让各种鸭子继承此超类。

    需求变更:让鸭子能够飞fly。

    方案1:在Duck类中加上fly()。

    结果:所有鸭子都继承fly,但并非所有鸭子都会飞,比如橡皮鸭RubberDuck(继承牵一发动全身)。

    方案1_1:对于不能飞的鸭子,在子类中覆盖fly()。

    结果:每当有新的鸭子出现,就要被迫检查并可能需要覆盖fly()。同理,对于叫声quack也一样。

    方案2:把fly()和quack()从超类中取出,放进Flyable和Quackable接口中,只会飞的鸭子实现Flyable,会叫的实现Quackable。

     

    结果:不会再有会飞的橡皮鸭,但由于接口不具有实现代码,造成代码无法复用(接口无法达到代码复用)。

    方案2_1:设计两个接口FlyBehavior和QuackBehavior,还有它们对应的类,负责实现具体行为。

    结果:飞行和呱呱叫动作可以被其他的对象复用,因为这些行为已经与鸭子类无关;可以新增一些行为,不会影响到既有的行为类,也不会影响使用飞行行为的鸭子类(有了继承的复用好处,没了继承所带来的包袱)。

    完善方案2_1:在Duck类中加入两个变量“flyBehavior”和“quackBehavior”,声明为接口类型,用performFly和performQuack分别取代fly和quack;同时加入两个新方法setFlyBehavior和setQuackBehavior,用来随时改变鸭子的行为。

    测试Duck的代码

    Duck类(Duck.java)

    public abstract class Duck {
        //所有鸭子子类都继承它
        FlyBehavior flyBehavior;
        QuackBehavior quackBehavior;
        public Duck(){
        }
        public abstract void display();
        
        public void perfmormFly(){
            //委托给行为类
            flyBehavior.fly();
        }
        public void performQuack(){
            //委托给行为类
            quackBehavior.quack();
        }
        public void setFlyBehavior(FlyBehavior fb){
            flyBehavior=fb;
        }
        public void setQuackBehavior(QuackBehavior cb){
            quackBehavior=cb;
        }
        public void swim(){
            System.out.println("All ducks float,even decoys!!");
        }
    }
    View Code

    MallardDuck类和ModelDuck类(MallardDuck.java与ModelDuck)

    public class MallardDuck extends Duck{
        public MallardDuck(){
            quackBehavior=new Quack();
            flyBehavior=new FlyWithSwings();
        }
        public void display(){
            System.out.println("I'm a real Mallard Duck");
        }
    }
    
    public class ModelDuck extends Duck{
        public ModelDuck(){
            flyBehavior=new FlyNoWay();
            quackBehavior=new MuteQuack();
        }
        public void display(){
            System.out.println("I'm a model duck!!");
        }
    }
    View Code

    FlyBehavior接口(FlyBehavior.java)与三个行为实现类(FlyWithWings.java、FlyNoWay.java和新增的FlyRocketPowered.java)

    public interface FlyBehavior {
        public void fly();
    }
    
    public class FlyWithSwings implements FlyBehavior{
        public void fly(){
            System.out.println("I'm flying!!");
        }
    }
    
    public class FlyNoWay implements FlyBehavior{
        public void fly(){
            System.out.println("I can't fly!!");
        }
    }
    
    public class FlyRocketPowered implements FlyBehavior{
        public void fly(){
            System.out.println("I'm flying with a rocket!!");
        }
    }
    View Code

    QuackBehavior接口(QuackBehavior.java)及其三个实现类(Quack.java、MuteQuack.java、Squeak.java)

     1 public interface QuackBehavior {
     2     public void quack();
     3 }
     4 
     5 public class Quack implements QuackBehavior{
     6     public void quack(){
     7         System.out.println("Quack!!");
     8     }
     9 }
    10 
    11 public class MuteQuack implements QuackBehavior{
    12     public void quack(){
    13         System.out.println("Silence!!");
    14     }
    15 }
    16 
    17 public class Squeak implements QuackBehavior{
    18     public void quack(){
    19         System.out.println("Squeak");
    20     }
    21 }
    View Code

     测试类(MiniDuckSimulator.java)

    public class MiniDuckSimulator {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Duck mallard=new MallardDuck();
            mallard.perfmormFly();
            mallard.performQuack();
            Duck model=new ModelDuck();
            model.perfmormFly();
            model.performQuack();
            model.setFlyBehavior(new FlyRocketPowered());
            model.perfmormFly();
        }
    }
    /*
     *
     * 运行结果:
     * Quack!!
     * I can't fly!!
     * Silence!!
     * I'm flying with a rocket!!
     */
    View Code

     

    这就是策略模式

    策略模式(Strategy Pattern)定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。封闭可以互换的行为,并使用委托来决定要使用哪一个。

    策略模式结构

    Strategy:可由接口或抽象类来实现;定义所有支持的算法的公共接口;Context使用这个接口来调用某ConcreteStrategy定义的算法。

    ConcreteStrategy:具体的策略实现,也就是具体的算法实现。

    Context:用一个ConcreteStrategy对象来配置;维护一个对Strategy对象的引用;可定义一个接口来让Strategy访问它的数据。

    策略模式示例代码

    /**
     * 策略,定义算法的接口
     */
    public interface Strategy {
        // 某个算法的接口,可以有传入参数,也可以有返回值
        public void algorithmInterface();
    }
    
    /**
     * 实现具体的算法
     */
    public class ConcreteStrategyA implements Strategy {
        public void algorithmInterface() {
           //具体的算法实现   
        }
    }
    public class ConcreteStrategyB implements Strategy {
        public void algorithmInterface() {
           //具体的算法实现   
        }
    }
    public class ConcreteStrategyC implements Strategy {
        public void algorithmInterface() {
           //具体的算法实现   
        }
    }
    
    /**
     * 上下文对象,通常会持有一个具体的策略对象
     */
    public class Context {
        //持有一个具体的策略对象
        private Strategy strategy;
    
         // 构造方法,传入一个具体的策略对象
         //@param aStrategy 具体的策略对象
        public Context(Strategy aStrategy) {
           this.strategy = aStrategy;
        }
    
         // 上下文对客户端提供的操作接口,可以有参数和返回值
        public void contextInterface() {
           //通常会转调具体的策略对象进行算法运算
           strategy.algorithmInterface();
        }
    }

    关于策略模式, 最后推荐一篇博文:http://www.uml.org.cn/sjms/201009092.asp

  • 相关阅读:
    PrimeNG之Validation
    PrimeNG之FileUpload
    PrimeNG之DataTable
    PrimeNG之TreeTable
    AngularJS实现可伸缩的页面切换
    ng2-table
    【转】前端框架天下三分:Angular React 和 Vue的比较
    【转】AngularJS动态生成div的ID
    Emprie 使用基础笔记
    开源沙箱CuckooSandbox 介绍与部署
  • 原文地址:https://www.cnblogs.com/aaron-shu/p/5096630.html
Copyright © 2011-2022 走看看