Posts 策略模式
Post
Cancel

策略模式

模拟鸭子应用

模拟鸭子游戏SimUDuck。游戏中会出现各种鸭子,一边游泳戏水,一边呱呱叫。此系统内部设计使用了标准的OO技术。设计了一个鸭子超类(Superclass),并让各种鸭子继承此超类。

新需求让鸭子能飞,在超类中添加fly()方法,但是,并非Duck所有的子类都会飞,比如橡皮鸭,在超类中添加新的行为,会使得某些并不适合该行为的子类也具有该行为。

利用继承将橡皮鸭的fly()方法覆盖掉变成什么事都不做,如果以后加入诱饵鸭(DecoyDuck),诱饵鸭是木头鸭子,不会飞也不会叫,需要覆盖fly()方法和quack()方法。而且,当有新的鸭子子类出现,就要被迫检查并可能需要覆盖fly()quark()

所以,需要一个更清晰的方法,让某些鸭子可飞或可叫。

虽然FlyableQuackable可以解决一部分问题,但是却造成代码无法复用

使用继承并不能很好地解决问题。

设计原则找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

把鸭子的行为从Duck类中取出来。Duck类内的fly()quack()会随着鸭子的不同而改变。为了要把这两个行为从Duck类中分开,我们将把它们从Duck类中取出来,建立一组新类来代表每个行为。

设计原则针对接口编程,而不是针对实现编程。

我们利用接口代表每个行为,比方说,FlyBehaviorQuackBehavior,而行为的每个实现都将实现其中的一个接口。

这样的设计,可以让飞行和呱呱叫的动作被其他的对象复用,因为这些行为已经与鸭子类无关了。

而我们可以新增一些行为,不会影响到既有的行为,也不会影响“使用”到飞行行为的鸭子类。

整合鸭子的行为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public abstract class Duck {
	QuackBehavior quackBehavior;
	FlyBehavior flyBehavior;
	public void performQuack(){
		quackBehavior.quack();
	}
	public void performFly(){
		flyBehavior.fly();
	}
	public void swim(){

	}
	public abstract display();
	public void swim(){
		System.out.println(" All ducks float,even decoys!");
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface FlyBehavior{
	public void fly();
}
public class FlyWithWings implements FlyBehavior{
	public void fly(){
		System.out.println("I'm flying!!");
	}
}

public class FlyNoWay implements FlyBehavior{
	public void fly(){
		System.out.println("I can't fly");
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface QuackBehavior{
	public void quack();
}
public class Quack implements QuackBehavior{
	public void quack(){
		System.out.println("Quack");
	}
}

public class MuteQuack implements QuackBehavior{
	public void quack(){
		System.out.println("<< Slience >>");
	}
}
public class Squeak implements QuackBehavior{
	public void quack(){
		System.out.println("Squeak");
	}
}

在子类中设定flyBehaviorquackBehavior

1
2
3
4
5
6
7
8
9
10
public class MallardDuck extends Duck{
	public MallardDuck(){
		quackBehavior = new Quack();
		flyBehavior = new FlyBehavior();
	}

	public void display(){
		System.out.println("I'm a real Mallard duck");
	}
}
1
2
3
4
5
6
7
public class MiniDuckSimulator{
	public abstract void main(String[] args){
		Duck mallard = new MallardDuck();
		mallard.performQuack();
		mallard.performFly();
	}
}

动态设定行为

1.在Duck类中,加入两个新方法:

1
2
3
4
5
6
public void setFlyBehavior(FlyBehavior fb){
	flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb){
	quackBehavior = qb;
}

2.制造一个新的鸭子类型:模型鸭(ModelDuck)

1
2
3
4
5
6
7
8
9
public class ModelDuck extends Duck {
	public ModelDuck(){
		flyBehavior = new FlyNoWay();
		quackBehavior = new Quack();
	}
	public void display(){
		System.out.println("I'm a model duck");
	}
}

3.建立一个新的FlyBehavior类型

1
2
3
4
5
public class FlyRocketPowered implements FlyBehavior {
	public void fly(){
		System.out.println("I'm flying with a rocket!");
	}
}

4.改变测试类,加上模型鸭,并使模型鸭具有火箭动力。

1
2
3
4
5
6
7
8
9
10
11
public class MiniDuckSimulator{
	public abstract void main(String[] args){
		Duck mallard = new MallardDuck();
		mallard.performQuack();
		mallard.performFly();
		Duck model = new ModelDuck();
		model.performFly();
		model.setFlyBehavior(new FlyRocketPowered());
		model.performFly();
	}
}

设计原则多用组合,少用继承。

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

This post is licensed under CC BY 4.0 by the author.