一、策略模式
策略模式:定义了算法族(其实就是has-a 类,这里把继承它的类叫做算法不叫行为),分别封装(比如setter)起来,让他们之间可以相互转换,此模式让算法的变化独立于使用算法的客户。
二、设计原则
1、找出应用中可能需要变化之处,把它们独立出来,不要和哪些不需要变化的代码混在一起。
2、针对接口编程,而不是针对实现编程.
比如:FlyBehavior与QuackBehavior,而行为的每个实现都将实现其中的一个接口,所以鸭子类不会负责实现Flying和Quacking接口,反而是由我们制造一组其他类专门实现FlyBehavior与QuackBehavior,这就称为“行为类”。由行为类而不是Duck类来实现接口。
3、多用组合,少用继承。即时多用has-a,少用is-a
三、代码实现
该代码主要是些”鸭子类“关于它”飞行“和”呱呱叫“的行为的例子
1、鸭子类
//鸭子抽象类
public abstract class Duck {
QuackBehavior quackBehavior; //呱呱叫行为
FlyBehavior flyBehavior; //飞行行为
/**动态设定行为可以让鸭子更新行为*/
public void setQuackBehavior(QuackBehavior quackBehavior) { //封装呱呱叫行为
this.quackBehavior = quackBehavior;
}
public void setFlyBehavior(FlyBehavior flyBehavior) { //封装飞行为
this.flyBehavior = flyBehavior;
}
public abstract void display();
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
public void swim(){
System.out.println("All ducks float,even decoys");
}
}
//绿头鸭
public class MallardDuck extends Duck{
public MallardDuck() {
// TODO Auto-generated constructor stub
quackBehavior = new Quack(); //实现呱呱叫接口
flyBehavior = new FlyWithWings(); //实现飞接口
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("I'am a real Mallard duck!");
}
}
//模型鸭
public class ModelDuck extends Duck{
public ModelDuck() {
// TODO Auto-generated constructor stub
quackBehavior = new Quack();
flyBehavior = new FlyNoWay(); //默认设置不会飞
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("I'm a ModelDuck");
}
}
2、飞行行为
飞行接口
public interface FlyBehavior {
public void fly();
}
//不会飞行为
public class FlyNoWay implements FlyBehavior{
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I can't fly");
}
}
//火箭发射器
public class FlyRoketPowered implements FlyBehavior{
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I'm flying with a roket");
}
}
//空中飞
public class FlyWithWings implements FlyBehavior{
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I'm flying!");
}
}
3、呱呱叫行为
public class Quack implements QuackBehavior{
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("Quack");
}
}
//呱呱叫
public class MuteQuack implements QuackBehavior{
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("<< Silence >>");
}
}
//沉默
public class MuteQuack implements QuackBehavior{
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("<< Silence >>");
}
}
4、运行函数
public class DoRun {
public static void main(String[] args) {
Duck mallard = new MallardDuck(); //超类型编程
/** 父类只需要调用方法就行,不需要知道具体实现方法 */
mallard.performFly();
mallard.performQuack();
mallard.display();
/**
* 在运行时想改变鸭子的行为,只需调用鸭子的setter方法即可
* */
Duck model = new ModelDuck();
model.display();
model.performFly();
model.setFlyBehavior(new FlyRoketPowered());
model.performFly();
}
}
四、封装行为大局观
五、总结
"has-a"关系相当的有趣:每一个鸭子都有FlyBehavior和一个QuackBehavior,将这两个”飞行“和”呱呱叫“行为委托给他们处理。
当你将两个类结合起来使用,如同本例一般,这就是组合。这种做法和”继承“不同的地方在于,鸭子的行为不是继承来的,而是和适当的对象”组合“来的。
如你所见,使用组合建立系统具有很大的弹性,不仅可将算法族封装成类,更可以”在运行时动态的改变行为“,只要组合的行为对象符合正确的接口标准即可。