策略模式 strategy

设计模式

场景:

现有子类具有某些功能相同,但是具体实现不同的方法。

书中例子

现有一个Duck类,具有fly 和 quack 方法。fly和quack有具体实现。

现在需要有另外多种鸭子类型,其中的fly和quack方法的实现不同。

未使用模式的设计

Untitled

DuckB和DuckC继承DuckA,并复写fly和quack方法

代码之后可能的变化

  1. 可能出现DuckD,具有fly、quack方法。
  2. 可能出现DuckE,具有的fly、quack方法和DuckA的fly相同,DuckC的quack相同,需要创建一个子类,同时fly和quack方法都重复了。

使用的原则

封装变化。

Duck的子类中的方法实现是改变的,但是这些方法的功能和调用这些方法的代码是不变的。

将这些需要改变的代码独立封装。

针对接口编程,而不是实现编程。

使用接口的多态必然可以应对实现类的变化,这也是封装变化的一种情形。

多用组合,少用继承。

由于继承已经确定了类之间的关系,只有当我们确定 A is B 是一个永远不会改变的情况下才使用继承。

定义及作用

策略模式定义了算法族,他们之间可以互相替换。

封装变化

封装了算法的变化,将相同功能但具体实现不同的算法封装成算法族。

使用策略模式的设计

Untitled

  1. 定义了算法族:Flyable 和 Quackable,其中的实现FlyableA和FlyableB是Flyable的情形永远不会改变,所以使用了继承。

  2. 使用了组合,可以动态的使用何种算法,达到复用功能。

    // 如果使用了接口中的继承,那么DuckA中的代码不能得到复用,需要全部实现。
    // 组合的复用和继承的的复用的区别,由于java中只能单继承,
    // 所以复用的所有方法都是相同的,除非覆写
    // 但是对于类对象,我们不建议覆写,因为会改变类的封装,如果需要覆写,不如继承虚拟类。
    interface Duck extends Flyable,Quackable{}
    class DuckA implements Duck{}
    
  3. 在Client中使用了创建的方式,后面可以使用工厂方式创建,而不具体指定类型。

    public class Client {
        public static void main(String[] args) {
            Duck duckA = new DuckA();
            Duck duckB = new DuckB();
            Duck duckC = new DuckC();
            List<Duck> ducks = Arrays.asList(duckA, duckB, duckC);
            ducks.forEach(Duck::fly);
            ducks.forEach(Duck::quack);
        }
    }
    

现已遇到的场景代码

posted @ 2022-04-07 14:55  leevi-ding  阅读(66)  评论(0编辑  收藏  举报