--------------------------------------------------根据《Head First 设计模式》整理记忆--------------------------------------------------------------------
从一个添加鸭子的行为讲起,一开始采用的是继承:
DUCK父类:
<span style="font-size:14px;">package StrategyPattern;
/**
* @author 作者 E-mail:
* @version 创建时间:2015年7月8日 上午10:37:42 类说明
*/
public class Duck {
public void quack() {
System.out
.println("-------------------Duck quack-----------------------");
}
public void swim() {
System.out
.println("-------------------Duck swim----------------------");
}
public void display() {
System.out
.println("-------------------Duck display-------------------");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
</span>
MallardDuck子类:
<span style="font-size:14px;">package StrategyPattern;
/**
* @author 作者 E-mail:
* @version 创建时间:2015年7月8日 上午10:40:05 类说明
*/
public class MallardDuck extends Duck {
public void display() {
System.out
.println("-------------------------MallardDuck display---------------------------");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
</span>
ReadheadDuck子类:
<span style="font-size:14px;">package StrategyPattern;
/**
* @author 作者 E-mail:
* @version 创建时间:2015年7月8日 上午10:41:13 类说明
*/
public class RedheadDuck extends Duck{
public void display() {
System.out
.println("-------------------------RedheadDuck display---------------------------");
}
public static void main(String[] args) {
RedheadDuck aRedheadDuck = new RedheadDuck();
aRedheadDuck.quack();
}
}
</span>
法一:后来需要添加一个fly行为,首先想到的是直接在父类里面添加fly方法,课本上说造成了满屏飞的鸭子(PS:这个我们一般不会犯这个错误,子类需要Override一下的)
如同dispal一样去实现这个行为:
缺点:
1.代码在多个子类重复;
2.运行时的行为不容易改变;
3.很难知道所有鸭子的行为;
4.改变会牵一发而动全身;
法二:MallardDuck继承Duck父类,然后实现Flyable接口,当鸭子种类很多时候噩梦发生,有很多的鸭子的飞行行为是相通的;
设计原则一:
找出其中可能需要变化之处,把他们独立出来,不要和那些需要变化的代码混在一起。
设计原则二:
针对接口编程,而不是针对实现编程。---关键在于利用多态---
法三:测试Duck的代码:
Duck类有两个行为类接口的引用:
package StrategyPattern;
/**
* @author 作者 E-mail:
* @version 创建时间:2015年7月8日 上午10:37:42 类说明
*/
public abstract class Duck {
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void swim() {
System.out
.println("-------------------Duck swim----------------------");
}
public void display() {
System.out
.println("-------------------Duck display-------------------");
}
public void performQuack() {//委托给行为类
quackBehavior.quack();
}
public void performFly() {//委托给行为类
flyBehavior.fly();
}
}
两个接口及其实现类为:
第一个飞行接口及其实现:
public interface FlyBehavior {
public void fly();
}
public class FlyNoWay {
<span style="white-space:pre"> </span>public void fly() {
<span style="white-space:pre"> </span>System.out
<span style="white-space:pre"> </span>.println("-------------------I can't fly-------------------");
<span style="white-space:pre"> </span>}
}
public class FlyWithWings implements FlyBehavior {
<span style="white-space:pre"> </span>public void fly() {
<span style="white-space:pre"> </span>System.out
<span style="white-space:pre"> </span>.println("-------------------FlyWithWings-------------------");
<span style="white-space:pre"> </span>}
}
第一个鸭子叫接口及其实现:
public interface QuackBehavior {
public void quack();
}
public class MuteQuack implements QuackBehavior{
<span style="white-space:pre"> </span>public void quack() {
<span style="white-space:pre"> </span>System.out
<span style="white-space:pre"> </span>.println("-------------------MuteQuack----------------------");
<span style="white-space:pre"> </span>}
}
public class Quack implements QuackBehavior {
<span style="white-space:pre"> </span>public void quack() {
<span style="white-space:pre"> </span>System.out
<span style="white-space:pre"> </span>.println("-------------------quack----------------------");
<span style="white-space:pre"> </span>}
}
public class Squeak implements QuackBehavior {
<span style="white-space:pre"> </span>public void quack() {
<span style="white-space:pre"> </span>System.out
<span style="white-space:pre"> </span>.println("-------------------Squeak----------------------");
<span style="white-space:pre"> </span>}
}
编写测试用例:
package StrategyPattern;
/**
* @author 作者 E-mail:
* @version 创建时间:2015年7月8日 上午10:40:05 类说明
*/
public class MallardDuck extends Duck {
public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
public void display() {
System.out
.println("-------------------MallardDuck display-------------------");
}
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performFly();
mallard.performQuack();
}
}
法四:动态设定行为,鸭子的行为可以动态变化的时候,这一秒旋转飞,下一秒倒着飞,就是这么任性,怎么办,以为上面已经把 鸭子的行为在构造器内实例化了,需要设置Setter方法去改变。
Duck父类添加两个方法去改变相应行为:
public void setQuackBehavior(QuackBehavior qb) {//委托给行为类
quackBehavior = qb;
}
public void setFlyBehavior(FlyBehavior fb) {//委托给行为类
flyBehavior = fb;
}
mallardDuck实例进行动态改变自己行为
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();
mallard.setFlyBehavior(new FlyNoWay());
mallard.performFly();
}
最后结果:
-------------------quack----------------------
-------------------FlyWithWings-------------------
-------------------I can't fly-------------------
总结:
策略者模式定义:定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。(这也就是为什么图3中为何把“行为”摸去改为算法的原因)
策略者模式的优点:
1、 提供了一种替代继承的方法,而且既保持了继承的优点(代码重用)还比继承更灵活(算法独立,可以任意扩展)。
2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
策略者模式的缺点:
1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
ps:GRASP(General Responsibility Assignment Software Pattern)是通用职责软件分配模式。GRASP的核心是自己干自己能干的事,自己只干自己的 事,也就是职责的分配和实现高内聚。用来解决面向对象设计的一些问题。此外GRASP原则还阐述了几大原则,以后会继续写博道来。
源代码:http://download.youkuaiyun.com/detail/bingbing8219/8879481