策略模式:定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
在学习策略模式过程中也学到了几个设计原则:
1. 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
2. 针对接口编程,而不是针对实现编程。
3. 多用组合,少用继承。(“有一个”可能比“是一个”更好)
下面是Head First设计模式中关于策略模式的实例,代码如下:
1 抽象Duck类,以及两个实例类MallardDuck和ModelDuck
Duck类
package test;
public abstract class Duck {
// 为行为接口类型声明两个引用变量,所有的鸭子类(在同一个package中)都继承它们
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public Duck() {
}
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!");
}
// 通过设定方法(setter
// method)来设定鸭子的行为,而不是在鸭子的构造器内实例化。通过setFlyBehavior和setQuackBehavior这两个方法,我们可以随时调用它们改变鸭子的行为。
public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
}
MallardDuck类
package test;
public class MallardDuck extends Duck {
// 在构造器中,将鸭子的飞行行为设定为FlyWithWings,同时将鸭子的叫声设置为Quack
public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
@Override
public void display() {
System.out.println("I'm real Mallard duck");
}
}
ModelDuck类
package test;
public class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
@Override
public void display() {
System.out.println("I'm a model duck");
}
}
FlyBehavior类
package test;
/**
* 所有飞行行为类必须实现的接口
*
* @author CYL
*
*/
public interface FlyBehavior {
public void fly();
}
FlyWithWings类
package test;
/**
* 飞行行为的实现,给真会飞的鸭子用
*
* @author CYL
*
*/
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("I'm flying!!");
}
}
FlyNoWay类
package test;
/**
* 这是飞行行为的实现,给不会飞的鸭子用(包括橡皮鸭和诱饵鸭)
*
* @author CYL
*
*/
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("I can't fly");
}
}
FlyRocketPowered类
package test;
/**
* 飞行行为实现类,在测试类中,用来讲述如何利用set method来改变鸭子行为
*
* @author CYL
*
*/
public class FlyRocketPowered implements FlyBehavior {
@Override
public void fly() {
System.out.println("I'm flying with a rocket!");
}
}
3. 鸭子叫声接口QuackBehavior,以及其三个具体实现类Quack、MuteQuack、Squeak
QuackBehavior接口
package test;
public interface QuackBehavior {
public void quack();
}
Quack类
package test;
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("Quack");
}
}
MuteQuack类
package test;
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("<<Silence>>");
}
}
Squeak类
package test;
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("Squeak");
}
}
4. 测试类MiniDuckSimulator
package test;
public class MiniDuckSimulator {
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();
Duck model = new ModelDuck();
// 第一次调用performFly()会被委托给flyBehavior对象(也就是FlyNoWay实例),该对象是在模型鸭构造器中设置的。
model.performFly();
// 这会调用set方法,把火箭动力飞行的行为设定到模型鸭中。模型鸭突然具有了火箭动力飞行能力。
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
Quack
I'm flying!!
I can't fly
I'm flying with a rocket!
小结:在策略模式中,对于应用中需要改变的部分,我们把它提出来,分别做成一个算法,然后封装到应用类中。这样能实现松耦合。