主要内容大概就是学习设计模式时一些笔记和心得。
参考书籍有
《Head First Design Patterns》
《Design Patterns : Elements of Reusable Object-Oriented Software》
《Implementation Patterns》。
从策略模式的定义可以看出,因为他们可以内部交换,所以这些算法肯定具有共同性,因此首先想到的就是这些实现这些算法的类继承自同一父类,当然在java中可能是实现了同一接口。这种内部可交换性如果对于使用者是透明的话,那么使用着肯定是通过调用基类的接口来向实例发送消息。
下面以《Head First Design Patterns》中介绍的例子来说明策略模式的用法。
首先需要定义参与者中的Context,本例中是class Duck,作为context一个比较重要的特性就是可以定义一个接口,让策略类访问它的内部数据,这个特性在本例中没有体现,稍后给出的《Design Patterns》中的示例代码中包含这个特性。
/** * Context class * - is configured with a ConcreteStrategy object * - maintains a reference to a Strategy object. * - may define an interface that lets Strategy access its data. * @author <Head First Design Pattern> */ public abstract class Duck { // References to Strategy objects. protected FlyBehavior flyBehavior; protected QuackBehavior quackBehavior; public Duck() { } public abstract void display(); public void performFly() { flyBehavior.fly(); } public void performQuack() { quackBehavior.quack(); } // Interfaces for changing behaviors dynamically. public void setFlyBehavior(FlyBehavior fb) { flyBehavior = fb; } public void setQuackBehaviro(QuackBehavior qb) { quackBehavior = qb; } public void swim() { System.out.println("All ducks float, even decoys!"); } }
然后是策略类,此处定义为一个接口类,Duck类可以利用此接口类中定义的共同方法去调用实例类中的算法。
public interface FlyBehavior { public void fly(); }
public interface QuackBehavior { public void quack(); }
如果是通过C++的模板类方法类实现策略模式,则不许要定义抽象接口。
接下来可以根据需要定义满足策略类接口的具体策略了。
public class FlyNoWay implements FlyBehavior { public void fly() { System.out.println("I can't fly"); } }
public class FlyRocketPowered implements FlyBehavior { public void fly() { System.out.println("I'm flying with a rocket!"); } }
public class FlyWidthWings implements FlyBehavior { public void fly() { System.out.println("I'm flying !!"); } }
public class MuteQuack implements QuackBehavior { public void quack() { System.out.println("<< Silence >>"); } }
public class Quack implements QuackBehavior { public void quack() { System.out.println("Quack"); } }
public class Squeak implements QuackBehavior { public void quack() { System.out.println("Squeak"); } }
通过定义可知,策略设计模式主要强调的是策略,即算法以及策略可以独立与客户端而动态改变。
因此为了使用设计模式以下Context的具体类并不是必须的,可以只存在一个Context。
public class MallardDuck extends Duck { public MallardDuck() { quackBehavior = new Quack(); flyBehavior = new FlyWidthWings(); } public void display() { System.out.println("I'm a real Mallard duck"); } }
public class ModelDuck extends Duck { public ModelDuck() { flyBehavior = new FlyNoWay(); quackBehavior = new Quack(); } public void display() { System.out.println("I'm a model duck"); } }客户端类主要负责控制Strategy与Client的结合。
public class MiniDuckSimulator { public static void main(String[] args) { Duck mallard = new MallardDuck(); mallard.performQuack(); mallard.performFly(); Duck model = new ModelDuck(); model.performFly(); model.setFlyBehavior(new FlyRocketPowered()); model.performFly(); } }这个例子比较形象的说明了策略模式的使用方法,但是在实际开发中策略类不可避免的要访问到client类的数据,
因此client类与strategy类之间如何以低耦合的方式交互有时候是比较重要的。
在GOF的设计模式中提供了两种思路
One approach is to have Context pass data in parameters to Strategy operations -- in other words, take the data to the strategy.
This keeps Strategy and Context decoupled. On the other hand, Context might pass data the Strategy doesn't need.
Another technique has a context pass itself as an argument, and the strategy requests data from the context explicitly.
当然最好的方式是取决与特定的算法与与之相关的数据需求。
策略模式的应用有编辑器,代码优化,金融设备等领域。