首页 > 技术文章 > 设计模式之策略模式(Strategy pattern)

limiracle 2014-08-11 15:43 原文

1、定义

策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

2、类图

image

Context封装角色:它也叫上下文角色,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。

Strategy抽象策略角色:策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。

ConreteStrategy:具体策略角色,实现抽象策略中的操作,该类含有具体的算法。

2、问题深入

现在有一个Duck(鸭子)的抽象类,抽象了鸭子的公共行为:quack、swim等,并有RedhadDuck继承此类,并拥有了Duck的所有公共的行为。代码如下:

package strategy;
/**
 * 所有鸭子父类,可以呱呱叫,可以游泳
 */
public class Duck {
    
    //呱呱叫
    public void quack(){
        
    }
    //游泳
    public void swim(){
        
    }
    //其他行为
    public void display(){
        
    }
    
}
package strategy;

/**
 * 红头鸭子,继承鸭子的所有行为
 */
public class RedhadDuck extends Duck{

}

现在进行改造:1、给duck添加一个fly行为;2、鸭子的叫声不光有“呱呱叫”还有“呀呀叫”;3、有些鸭子可以叫,有些鸭子不可以叫;4、有些鸭子可以飞,有些鸭子不可以飞

实现方案:

  • 在Duck类中添加fly()方法 实现fly的行为
  • 添加 “呀呀叫”的方法,实现呀呀叫的行为
  • 在具体的duck实例中重写“叫”的方法,实现具体的是否可以叫
  • 在具体的duck实例中重写fly方法,实现具体的是否可以fly

缺点:这种实现方案中,若添加一个鸭子实例,则要重写每一个fly和quack方法,代码重复太大。

解决:找出应用中可能需要变化的东西,把他们独立出来,不要把他们和不需要变化的代码混在一起。我们把fly和quack独立出来,单独新建一个新类来表示fly和quack的行为。代码如下:

package strategy;
/**
 * 鸭子的飞行行为
 */
public interface FlyBehavior {
    public void fly();
}
package strategy;

public class FlyNoWay implements FlyBehavior{
    public void fly() {
    }
}
package strategy;

public class FlyWithWings implements FlyBehavior{
    //实现飞行方法
    public void fly() {
        System.out.println("FlyWithWings~~");
    }
}
package strategy;
/**
 * 叫的行为
 */
public interface QuackBehavior {
    public void quack();
}
package strategy;

public class Quack implements QuackBehavior{
    public void quack() {
        System.out.println("呱呱叫~");
    }

}
package strategy;

public class Squeak implements QuackBehavior{
    public void quack() {
        System.out.println("吱吱叫~");
    }

}
package strategy;

/**
 * 红头鸭子,继承鸭子的所有行为
 */
public class RedhadDuck extends Duck{

}
package strategy;
/**
 * 所有鸭子父类
 */
public class Duck {
    
    public FlyBehavior flyBehavior;
    public QuackBehavior quackBehavior;
    
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior = quackBehavior;
    }
    
    //
    public void quack(){
        quackBehavior.quack();//委托给行为类
    }
    public void fly(){
        flyBehavior.fly();//委托给行为类
    }
    //游泳
    public void swim(){
        
    }
    //其他行为
    public void display(){
        
    }
    
}
package strategy;

public class Main {

    public static void main(String[] args) {
        Duck duck=new RedhadDuck();
        duck.setFlyBehavior(new FlyWithWings());
        duck.setQuackBehavior(new Squeak());
        duck.fly();
        duck.quack();
    }

}

设计原则:多用组合,少用集成

推荐阅读