设计模式---策略者模式

--------------------------------------------------根据《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.csdn.net/detail/bingbing8219/8879481





























發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章