策略模式(Strategy Pattern)(二):HeadFirst中鸭子的实现

一、问题描述


joe上班的公司做了一套成功的模拟鸭子的游戏:SimUDuck,游戏中会出现各种鸭子,一边游泳,一边呱呱叫,由于公司竞争压力加剧,必须重新设计鸭子(Duck)类,要求是:便于产生新的鸭子对象,可为鸭子添加新的行为,易于维护,动态设置行为。



二、类图


策略模式(Strategy Pattern)(二):HeadFirst中鸭子的实现_第1张图片

说明:

1.对各种鸭子的解释:

    RedHeadDuck:红头鸭,可以用翅膀飞,呱呱叫。

    RubberDuck:橡皮鸭,不会飞,吱吱叫。

    ModelDuck:模型鸭,不会飞,呱呱叫。

    DecoyDuck:诱饵鸭,不会飞,不会叫。

    MallardDuck:野鸭,会用翅膀飞,呱呱叫。


2.Duck是各种鸭子的抽象超类,其内部持有FlyBehavior和QuackBehavior接口类型的引用,因为飞行行为和呱呱叫行为随鸭子的不用而不同,是变化的部分,所以将它们取出并“封装”起来,好让其他部分不会受到影响。

       使用FlyBehavior和QuackBehavior接口类型便于以后增加新的飞行行为或呱呱叫行为,不会影响到既有的行为类,也不会影响使用行为的鸭子类。同样,这也可以让飞行行为和呱呱叫行为被其他对象复用,因为这些行为已经与鸭子类无关了,你也可以将其用在鸡和大鹅身上。


3.对飞行行为的解释:

    FlyWithWings用翅膀飞。

    FlyNoWay:不会飞。

    FlyRocketPowered:使用火箭动力飞行(鸭子的飞行行为可以动态改变)。


4.对呱呱叫(此呱呱叫泛指鸭子的叫声而不是红头鸭的“呱呱叫”)行为的解释:

    Quack:呱呱叫。

    FakeQuack:假叫。

    Squeak:吱吱叫。

    MuteQuack:不会叫。


5.所有的鸭子都会浮水,所以将swim()方法定义且实现为抽象父类Duck中的具体类。

所有的鸭子的外观随鸭子种类不同而不同,所以将display()方法定义为Duck中的抽象方法,让各个鸭子子类实现。


6.Duck中的performFly()和performQuack()方法:

  鸭子对象不亲自处理飞行行为和呱呱叫行为,而是委托给飞行行为类FlyBehavior和呱呱叫行为类QuackBehavior。例如performFly()方法实现为

	public void performFly() {
		flyBehavior.fly();
	}

7.Duck的setFlyBehavior()和setQuackBehavior()用于动态设置鸭子的行为。


8.类不仅可以表示具体的“东西”,还.可以用一个类来表示行为,FlyBehavior表示飞行行为,QuackBehavior表示呱呱叫行为。



三、代码实现


1.鸭子超类Duck:

public abstract class Duck {
	FlyBehavior flyBehavior;
	QuackBehavior quackBehavior;
 
	public Duck() {
	}
        //动态设置飞行行为
	public void setFlyBehavior (FlyBehavior fb) {
		flyBehavior = fb;
	}
 
	public void setQuackBehavior(QuackBehavior qb) {
		quackBehavior = qb;
	}
        //不同的鸭子长相不同
	abstract void display();
        //将飞行行为委托给飞行行为类处理
	public void performFly() {
		flyBehavior.fly();
	}
        //将呱呱叫行为委托给呱呱叫行为类处理
	public void performQuack() {
		quackBehavior.quack();
	}
        //所有鸭子都会浮水
	public void swim() {
		System.out.println("All ducks float, even decoys!");
	}
}

2.行为:


(1)飞行行为FlyBehavior:

public interface FlyBehavior {
	public void fly();
}

(2)呱呱叫行为QuackBehavior:

public interface QuackBehavior {
	public void quack();
}

3.具体的行为:


(1)飞行行为:


用翅膀飞:

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");
	}
}

使用火箭动力飞:

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

(2)呱呱叫行为:


呱呱叫:

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

吱吱叫:

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

假叫:

public class FakeQuack implements QuackBehavior {
	public void quack() {
		System.out.println("Qwak");
	}
}

不会叫:

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

4.各种鸭子


红头鸭:

public class RedHeadDuck extends Duck {
 
	public RedHeadDuck() {
		flyBehavior = new FlyWithWings();
		quackBehavior = new Quack();
	}
 
	public void display() {
		System.out.println("I'm a real Red Headed 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");
	}
}

野鸭:

public class MallardDuck extends Duck {
 
	public MallardDuck() {
		quackBehavior = new Quack();
        flyBehavior = new FlyWithWings();
	}
 
	public void display() {
		System.out.println("I'm a real Mallard duck");
	}
}

橡皮鸭:

public class RubberDuck extends Duck {
 
	public RubberDuck() {
		flyBehavior = new FlyNoWay();
		quackBehavior = new Squeak();
	}
 
	public void display() {
		System.out.println("I'm a rubber duckie");
	}
}

诱饵鸭:

public class DecoyDuck extends Duck {
	public DecoyDuck() {
		setFlyBehavior(new FlyNoWay());
		setQuackBehavior(new MuteQuack());
	}
	public void display() {
		System.out.println("I'm a duck Decoy");
	}
}


5.测试

public class MiniDuckSimulator {
 
	public static void main(String[] args) {
 
		MallardDuck	mallard = new MallardDuck();
		RubberDuck	rubberDuckie = new RubberDuck();
		DecoyDuck	decoy = new DecoyDuck();
 
		ModelDuck	model = new ModelDuck();

		mallard.performQuack();
		rubberDuckie.performQuack();
		decoy.performQuack();
   
		model.performFly();	
		model.setFlyBehavior(new FlyRocketPowered());
		model.performFly();
	}
}


四、体现的设计原则


(1)封装变化


鸭子的飞行行为和呱呱叫行为都是变化的,将它们封装到两个行为类中,在以后可以轻易地改动或扩充行为而不影响其他部分,系统更有弹性。


(2)多用组合,少用继承


Duck内部持有FlyBehavior和QuackBehavior的引用,鸭子的行为是和行为对象“组合”而来的,使系统具有很大的弹性,并且可以动态设置行为。


(3)针对接口编程,不针对实现编程


Duck内部的属性flyBehavior和quackBehavior都是接口类型的,将具体行为与鸭子类分离开来,实现了解耦,并且我们能够在运行时通过多态的魔力动态地指定行为的不同的实现类。



转载请注明出处:http://blog.csdn.net/jialinqiang/article/details/8871327

你可能感兴趣的:(java,设计模式,strategy,Headfirst)