策略模式 strategy
场景:
现有子类具有某些功能相同,但是具体实现不同的方法。
书中例子
现有一个Duck类,具有fly 和 quack 方法。fly和quack有具体实现。
现在需要有另外多种鸭子类型,其中的fly和quack方法的实现不同。
未使用模式的设计
DuckB和DuckC继承DuckA,并复写fly和quack方法
代码之后可能的变化
- 可能出现DuckD,具有fly、quack方法。
- 可能出现DuckE,具有的fly、quack方法和DuckA的fly相同,DuckC的quack相同,需要创建一个子类,同时fly和quack方法都重复了。
使用的原则
封装变化。
Duck的子类中的方法实现是改变的,但是这些方法的功能和调用这些方法的代码是不变的。
将这些需要改变的代码独立封装。
针对接口编程,而不是实现编程。
使用接口的多态必然可以应对实现类的变化,这也是封装变化的一种情形。
多用组合,少用继承。
由于继承已经确定了类之间的关系,只有当我们确定 A is B
是一个永远不会改变的情况下才使用继承。
定义及作用
策略模式定义了算法族,他们之间可以互相替换。
封装变化
封装了算法的变化,将相同功能但具体实现不同的算法封装成算法族。
使用策略模式的设计
-
定义了算法族:Flyable 和 Quackable,其中的实现FlyableA和FlyableB是Flyable的情形永远不会改变,所以使用了继承。
-
使用了组合,可以动态的使用何种算法,达到复用功能。
// 如果使用了接口中的继承,那么DuckA中的代码不能得到复用,需要全部实现。 // 组合的复用和继承的的复用的区别,由于java中只能单继承, // 所以复用的所有方法都是相同的,除非覆写 // 但是对于类对象,我们不建议覆写,因为会改变类的封装,如果需要覆写,不如继承虚拟类。 interface Duck extends Flyable,Quackable{} class DuckA implements Duck{}
-
在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); } }
现已遇到的场景代码
邮箱:noamand.ding@qq.com
Gitte: https://gitee.com/noamand