以下内容学习自《Head First 设计模式》以及
Justin's Tech Blog,由本人概括整理。
定义:
The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.(策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。)
怎么理解策略模式的定义呢?先大概整理说明一下这个来自head first中Duck的例子。
场景条件:鸭子都有swim、quack、fly行为,这里假定所有的鸭子都会游泳。
问题:现在要实现各种不同的鸭子(子类),不同的鸭子有不同的display。
解决方案:
1、将Duck设置为抽象类,实现swim、quack、fly方法,抽象display方法。所有的子类都继承自Duck,实现display。
存在的问题:有的鸭子会叫,有的不会叫。同样的,有的会飞,有的不会飞。所以在抽象类里面实现quack和fly方法不可行。
2、将quack和fly方法抽离出来,分别作为两个接口的方法,根据鸭子会不会飞、会不会叫独立的实现一个接口或者两个接口。
存在问题:如果有很多的子类,那么每个子类都需要实现这两个接口,并且有很多子类所表现出来的quack和fly行为一样,这么一来很有可能将quack和fly重复实现了很多次,这是一种冗余,而且也是无谓的工作。
3、策略模式:接口将系统的不同部分隔离开来(方法的具体实现隔离开),同时又将它们连接在一起(接口的行为放在一起,不同的行为相当于系统的不同部分。)
先看一个具体的例子:
定义两个接口,将quack和fly方法抽离出来。
public interface FlyBehavior {
public Object Fly();//将具体实现抽离出来
}
public interface QuackBehavior {
public Object Quack();
}
定义几个类,实现这两个接口。
public class FlyNoWay implements FlyBehavior {
@Override
public Object Fly() { //定义具体的实现
return "不会飞";
}
}
public class FlyWithWings implements FlyBehavior {
@Override
public Object Fly() { //有多少方式就有多少实现
return "我飞啦!";
}
}
public class Quack1 implements QuackBehavior {
@Override
public Object Quack() {
return "嘎嘎";
}
}
public class Quack1 implements QuackBehavior {
@Override
public Object Quack() {
return "吱吱";
}
}
实现子类继承Duck
public class RedHeadDuck extends Duck {
public RedHeadDuck(){
super.setFlyBehavior(new FlyWithWings());//根据不同的需求把实现set到相应的步骤当中。
super.setQuackBehavior(new Quack1());
}
@Override
public Object display() {
return "我是一只红头鸭";
}
}
public class RubberDuck extends Duck {
public RubberDuck() {
super.setFlyBehavior(new FlyNoWay());
super.setQuackBehavior(new Quack2());
}
@Override
public Object display() {
return "我是一只橡皮鸭";
}
}
运行以及运行结果:
public class Strategy {
public static void main(String[] args) {
RedHeadDuck redHeadDuck = new RedHeadDuck();
RubberDuck rubberDuck = new RubberDuck();
System.out.println(redHeadDuck.display()+","+redHeadDuck.fly()+","+redHeadDuck.quack()); //相同的方法,但由于set了不同的实现,所以表现出了不同的结果
System.out.println(rubberDuck.display()+","+rubberDuck.fly()+","+rubberDuck.quack());
}
}
我是一只红头鸭,我飞啦!,嘎嘎
我是一只橡皮鸭,不会飞,吱吱
这里打个比方,对于一件事情,有相同的步骤。不同的人去做,可能步骤的顺序不一样,每一步的具体实现方法也不一样。我们需要的就是把步骤的具体实现抽离出来,有多少不同的实现,就具体定义多少不同的实现。对于不同的人,只需要对于不同的步骤,选择自己的实现方法就行。
上例中fly、quack方法相当于“步骤”,FlyNoWay和FlyWithWings相当于步骤的具体实现。根据不同的需要,把实现set到相应的步骤当中。
这时返回到策略的定义,“算法”在这里指的就是FlyBehavior和QuackBehavior的不同实现。
策略模式的优点不多说,但是缺点也是显而易见的。
因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。