• 设计模式之策略模式


    《Head First 设计模式》,好书!

    策略模式经典的例子:鸭子模型

    假设我们主要研究鸭子(DUCK)的"叫(quack)"和鸭子的飞(fly)。

    public abstract class Duck{
      //呱呱
      quack();
      //
       fly();
    }

          1.假如,我们想要很多种鸭子在屏幕上飞和叫,想到了设计一个DUCK父类,让许许多多的鸭子子类继承fly()和quack()。这样鸭子们就可以自由的在屏幕飞和叫了。

          2.问题来了,屏幕上有个RubberDuck(橡皮鸭)在飞和呱呱叫,这怎么行!RubberDuck不会飞并且叫声是"吱吱"而不是"呱呱"。于是灵机一动,把RubberDuck

    的fly()和quack()重写,覆盖父类方法。屏幕看上去舒服多了~

         3.屏幕上怎么又多出来了一个DecoyDuck(诱饵鸭,木头制作),再重写父类方法,让它不会飞也不会叫。

         4.....不一会就感到厌烦了,老是重写了父类方法怎么行。

    直接继承有太多的缺点:

    • 代码在多个子类中重复(一直重写父类方法有木有)
    • 运行时行为不容易改变(我的DecoyDuck现在会飞了,能不能在运行的时候改变它)
    • 很难知道所有鸭子的全部行为(总不会把所有子类数一遍吧)
    • 牵一发而动全身

    于是,我们要改变设计方法。

    这些行为(fly和quack)继承起来太难控制,用接口把。嗯~把它们从DUCK父类中提取出来,分别定义一个接口。

    设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混合在一起。


    鸭子发出的声音不一样,可以"呱呱Quack"、"吱吱Squack"、"无声MuteQuack",分别实现fly的接口(FlyBehavior)

    这样,鸭子发出quack的时候就可以调用特定的方法。

    因为分离出来,这些行为和鸭子完全无关。实现青蛙的时候也可以拿走"呱呱叫"的方法

    设计原则:针对接口编程,不针对实现编程。

    /*
      Dog继承Animal
    */
    
    //针对实现编程
    Dog d = new Dog;
    d.bark();
    
    //针对接口编程,这里就是多态。
    Animal animal = new Dog();
    animal.bark();
    
    //用animal调用bark()方法,至于animal是什么,我们并不关心。

    那么还有一个问题,每个鸭子都去实现特定的行为方法(如:Quack),这些行为是固定的。可是我想在运行时动态的改变鸭子的行为怎么办?

    比如,DecoyDuck突然可以飞了。

    貌似可以用多态,针对接口编程。"叫"定义了接口QuackBehavior,"飞"定义了接口FlyBehavior。

    然后Quack(呱呱叫),SQuack(吱吱叫),MuteQuack(无声)实现了QuackBehavior。

    同理,FlyBehavior也有具体实现。

    那么,父类Duck:

    public abstract class Duck{
    
    //声明QuackBehavior的接口
    QuackBehavior quackBehavior;
    
    //鸭子对象不直接执行叫的行为,委托给quackBehavior对象。
    public void performQuack(){
       quackBehavior.quack();
    }
    //可以动态的修改行为,用quackBehavior来什么行为要什么行为。
    //比如传入MuteQuack,然后在调用performQuack,是不是就相当于 MuteQuack.quack(),不发声了。
    public void setQuackBehavior(QuackBehavior qb){
    quackBehavior = qb;
    } }

    有一个performQuack()方法,这个方法代替被删除的quack方法(直接继承的quack方法,在最上面)。

    作用就是去使用接口对象 quackBehavior调用quack方法。(或许画上类图更清楚)

    //叫的接口
    public interface QuackBehacior{
       public void quack();
    }
    
    ------------------------------------具体实现--------------------------------------
    public class Quack implements QuackBehavior{
       public void quack(){
       System.out.println("我会呱呱叫");
    }
    }
    ----------            ------------
    public class Squack implements QuackBehavior{
       public void quack(){
       System.out.println("我会吱吱叫");
    }
    }
    ----------            ------------
    public class MuteQuack implements QuackBehavior{
       public void quack(){
       System.out.println("我不会发声");
    }
    }

    像不像上面anmial和dog的调用,不需要知道具体是谁,委托给接口对象(可以这样理解吧)。

    那么,开始了

    写一个鸭子类继承Duck

    public MallardDuck extends Duck{
    
    public MallardDuck(){
    //quackBehavior是继承下来的
    quackBehavior = new Quack();
    }
    
    }

    开始测试:

    public static void main(String [] args){
    
    Duck mallard = new MallardDuck();
    mallard.performQuack(); //输出呱呱叫
    mallard.setQuackBehavior(new MuteQuack());
    mallard.performQuack();//输出无声
    
    }
    
    /*
    可能你还有些迷糊,那逐一解释代码
    1.Duck mallard = new MallardDuck()
    执行:
            quackBehavior = new Quack()//就像实例化了quackBehavior
    2.mallard.peiformQuack();
    执行:      
            quackBehavior.quack();//该对象调用Quack类里的quack()方法
    
    3.mallard.setQuackBehavior(new MuteQuack());
             quackBehavior = qb; //qb是不是 new MuteQuack();
    
    是不是所有的都是围绕QuackBehavior 接口,针对接口编程。
    */

    设计原则:多用组合(composition),少用继承

      上文中的fly(实现方式和quack相同)、quack行为就是组合。鸭子的行为不是继承来的,而是多个行为 组合 来的。

    这些行为完全可以被青蛙(呱呱),麻雀(飞)使用,提升了代码的复用程度。

    把"行为"抽象一下,不再叫做行为而是算法族。然后把他们封装起来(嗯,封装),可以动态的相互替换(鸭子的行为动态替换)。并且这些算法和要使用这些算法的鸭子没有任何关系。

    总结:

     策略模式定义了算法族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

    这样看起来是不是很高大上~

    转载请注明出处。http://www.cnblogs.com/yuhanghzsd/p/5357981.html

  • 相关阅读:
    uwsgi 的启动停止重启
    项目部署(Python3 + ubuntu 16.04(ali server) + Nginx + uWSGI + Django 1.11)
    阿里云连接上Mysql数据库(10061 errors)
    本地数据库上传到阿里云Mysql
    Django 用户的修改密码接口
    django 的忘记密码接口
    Git光速入门
    缓存问题:一致性、穿击、穿透、雪崩、污染
    redis进阶-高可用:主从复制详解
    Redis分片技术(Redis Cluster)
  • 原文地址:https://www.cnblogs.com/yuhanghzsd/p/5357981.html
Copyright © 2020-2023  润新知