Java设计模式——策略模式

Java设计模式之策略模式

设计模式基础:

  • 抽象
  • 多态
  • 继承
  • 组合

设计原则:

  • 把变化的抽取出来,不要和不变化的放在一起

  • 针对接口编程,不针对实现编程

  • 多用组合,少用继承

我们先把定义提出来:

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

这个概念比较难理解,下面我们具体通过案例分析一下

场景:我们有三个不同种类的程序员,JavaWeb、大数据BigData和Ai人工智能程序员;他们都有相同的喝水和睡觉行为,但是有不同的写代码行为(写JavaWeb,写Ai,写Big data),我们想一下怎么实现?

我们首先想到的是使用继承重写父类的方法实现,但是这样做的缺点很多:

Class JavaWebProgrammer extends Programmer{
    public void doSleeping(){
        //重写代码
    }
    public void doCoding(){
        //重写代码
    }
}
  • 可以解决问题,但是代码无法复用
  • 多一个类都要重新写它对应的实现,代码量太大
  • 不符合三个设计原则
  • 而且无法解决有些类没有或者不需要基类的某个功能 比如有的程序员退休了,有的没有退休

此时,针对某个类不需要实现基类某个功能你又想到了在重写中什么都不做的方法:

public void retired(){
    //do noting
}

但是这样依然没有解决上面的根本问题,所以我们又想到了使用接口:把不会变化的功能(睡觉行为和喝水行为依然放在基类里,会变化的行为(写代码行为)写成一个接口Codeable,然后通过继承基类实现不变的行为,实现Codeable接口实现不同的写代码行为

但是这么做还是不行:

  • 如果有很多子类的实现需要修改,那么我们要修改很多的代码

这个时候我们就应该充分考虑设计原则的作用了

  • 把变化的部分封装起来
  • 面向接口编程

大家就可以想到把接口的实现独立成一个个类,把写代码行为写成一个接口,不同的实现对应不同的实现类,然后我们在使用时,想到了多态的奇妙之处,根据多态的动态调用

如下:

ProgramBehavior programBehavior = new JavaWebBehavior();
programBehavior.doCoding();

在此,我们大体思路已经很接近成功了

  • 首先基类声明为抽象类,里面有睡觉和喝水行为的具体实现(不变的)

        protected void doDrinking(){
            System.out.println("I am drinking.");
        }
        protected void doSleeping(){
            System.out.println("I am sleeping");
        }
  • 在基类中声明变化的部分,使用接口的形式使得我们可以动态调用

    ProgramBehavior programBehavior;
    void doCoding(){
        programBehavior.doCoding();
    }
  • 创建写代码行为的接口

    public interface ProgramBehavior {
        void doCoding();
    }
  • 子类AIProgrammer继承抽象类Programmer,只需要在初始化时创建AIBehavior赋给我们基类的接口programBehavior

    public class AIProgrammer extends Programmer {
        public AIProgrammer(){
            programBehavior = new AIBehavior();
        }
    }
  • 创建不同的接口实现类,实现不同的写代码行为

    public class AIBehavior implements ProgramBehavior {
        @Override
        public void doCoding() {
            System.out.println("I am doing AI coding.");
        }
    }
  • 测试

    public void testAI(){
            Programmer aiProgrammer = new AIProgrammer();
            aiProgrammer.doDrinking();
            aiProgrammer.doCoding();
            aiProgrammer.doSleeping();
        }

    结果如下:

可见:我们使用多态动态调用了doCoding()方法,我们在需要修改实现的时候只需要需要修改接口对应的实现就可以了,而不需要修改子类的方法

当然,我们不应该在开发中使用初始化时创建实现类的这种方式,我们可以在基类中添加一个setProgramBehavior的方法,这样我们就可以在应用中动态的设置行为

void setProgramBehavior(ProgramBehavior programBehavior){
        this.programBehavior = programBehavior;
}

我们为AIProgramer在执行完睡觉后2秒设置一个新的写代码行为(退休)并调用

public class RetireBehavior implements ProgramBehavior {
    @Override
    public void doCoding() {
        System.out.println("I am retired just few days.");
    }
}

该AIProgramer类图如下

至此,这就是整个策略模式的设计方法,我们再来理一遍,也许你再去看策略模式的定义就没问题了(代码最后附上)

我们把行为中(每个行为可以看成一个算法,形成了算法族)变化的部分从基类抽象类中抽取出来,使用接口定义并使用类实现接口来实现某一个行为(算法)不同的表现,再利用多态的神奇之处动态调用接口不同实现类的同一方法;然后我们需要改变接口实现类的实现方法(算法)时对调用该方法的客户完成不需要更改,没有任何影响。

代码地址:Github策略模式


Java设计模式|策略模式

Java设计模式|观察者模式

Java设计模式|装饰者模式

Java设计模式|工厂模式

Java设计模式|命令模式

Java设计模式|适配器模式和外观模式

Java设计模式|模板方法模式

Java设计模式|迭代器模式和组合模式

Java设计模式|状态模式

Java设计模式|代理模式

Java设计模式|单例模式

Java设计模式|备忘录模式

Java设计模式|访问者模式

Java设计模式|复合模式

Java设计模式|桥接模式

Java设计模式|生成器模式

Java设计模式|享元模式/蝇量模式

Java设计模式|原型模式

Java设计模式|责任链模式

Java设计模式|中介者模式

  • 本文作者: dzou | 微信:17856530567
  • 本文链接: http://www.dzou.top/post/6c84d9a1.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
  • 并保留本声明和上方二维码。感谢您的阅读和支持!