【0】README
0.1)本文部分文字描述转自 “head first 设计模式”,旨在学习 设计模式入门(策略模式) 的基础知识;
0.2)本文章节4和5的source code,参见 设计模式——策略模式源代码
【1】看个荔枝(从模拟鸭子应用说起)
1.1)我们让鸭子飞起来:
method1)利用继承实现:在Duck中加入 fly() 方法,不过并不是所有的鸭子都会飞,比如橡皮鸭子;(干货——继承所出现的问题)Attention)利用继承来提供Duck的行为,这会导致下列哪些缺点(defects):
d1)代码在多个子类中重复;d2)运行时的行为不容易改变;d3)很难知道所有鸭子的全部行为;d4)改变会牵一发而动全身,造成其他鸭子不想要的改变;
method2)利用接口实现:这将导致一个问题,虽然Flyable 和 Quackable 可以解决问题,但是代码不能复用;(干货——接口实现所出现的问题)
【2】设计原则
2.1)原则1:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起;
2.2)原则2:针对接口编程,而不是针对实现编程;
2.3)针对接口编程的真正意思是:针对超类编程,可以更明确地说成“变量的声明类型应该是超类型,可以是一个抽象类或一个接口,只要是具体实现此超类的子类,都可以指定给这个变量”;
(干货——针对接口编程)
【3】solution——如何实现鸭子的行为(我们应该在鸭子类中包含设定行为的方法,这样就可以在运行时动态地改变绿头鸭的行为。)
3.1)我们有两个接口——FlyBehavior 和 QuackBehavior;
3.2)对以上设计的分析(Analysis):
A1)这样一来,可以让飞行和呱呱叫(quack)的动作被其他对象复用,因为这些行为与鸭子类无关了;A2)而我们新增一些行为,不会影响到既有的行为类,也不会影响 使用这些行为的 具体类,如鸭子类;
【4】整合鸭子的行为
4.1)关键在于: 鸭子现在会将飞行和呱呱叫的动作委托别人进行处理,而不是使用定义在Duck类内的 呱呱叫和飞行方法;
4.2)整合后的代码如下:
【5】动态设定行为
5.1)我们想通过在鸭子子类中通过“设定方法”来设定鸭子的行为,而不是在鸭子的构造器内实例化;
step1)在Duck类中,加入两个新方法: setFlyBehavior 和 setQuackBehavior;package com.designpattern.chapter0; public abstract class Duck { FlyBehavior flyBehavior; QuackBehavior quackBehavior; public Duck(){ } public void setFlyBehavior(FlyBehavior fb){ flyBehavior = fb; } public void setQuackBehavior(QuackBehavior qb){ quackBehavior = qb; } public abstract void display(); public void performFly(){ flyBehavior.fly(); } public void performQuack(){ quackBehavior.quack(); } public void swim(){ System.out.println("i am swiming!"); } }
step2)制造一个新的鸭子类型:模型鸭(ModelDuck.java)package com.designpattern.chapter0; public class ModelDuck extends Duck{ public ModelDuck(){ quackBehavior = new Quack(); flyBehavior = new FlyWithWings(); } @Override public void display() { System.out.println("i am a model duck!"); } }
step3)建立一个新的 FlyBehavior 类型(FlyRocketPowered.java)package com.designpattern.chapter0; public class FlyRocketPowered implements FlyBehavior{ @Override public void fly() { System.out.println("i am flying with rocket power!"); } }
step4)改变测试类,加入模型鸭,并使模型鸭具有火箭动力;package com.designpattern.chapter0; public class ModelDuckSimulator { public static void main(String[] args) { Duck mallard = new MallardDuck(); mallard.performQuack(); mallard.performFly(); Duck modelDuck = new ModelDuck(); modelDuck.performFly(); modelDuck.setFlyBehavior(new FlyRocketPowered()); modelDuck.performFly(); } }
5.2)组合定义:
将两个类结合起来使用,这就是组合。这种做法和继承不同的地方在于,鸭子的行为不是继承来的,而是和适当的行为对象组合来的;
5.3)设计原则: 多用组合,少用继承;
【6】封装行为的大局观
6.1)下面是整个重新设计后的类结构,你所期望的一切都有: 鸭子继承Duck,飞行行为实现 FlyBehavior接口,呱呱叫行为实现 QuackBehavior接口;
6.2)我们不再把鸭子的行为说成是 一组行为,而是将其想象成“一族算法”;
6.3)策略模式定义: 策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户;
(干货——策略模式定义)
【7】策略模式总结:
7.1)OO原则(rules):
r 1)封装变化;r2)多用组合,少用继承;r3)针对接口编程,不针对实现编程;
7.2)OO模式(pattern):
策略模式——策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户;