1. 问题引出
设计一个鸭子基类(Duck),并由这个基类派生多个子类鸭子(MallardDuck,RedheadDuck,.......)。鸭子基类中可能包含以下方法让子类继承或者重载quack(),swim(),fly()和display()等等。
如果我们使用简单的继承和implements interface的方式有以下缺点:1.如果使用继承,某些鸭子的行为在子类里不断的改变,并且让所有的子类都有这些行为是不恰当的,例如玩具鸭子不能飞(不应该继承fly()方法)。2.实现Flyable和Quackable接口,看似解决了问题(只有会飞的鸭子才继承Flyable接口),但是java接口不具有实现代码,所以implements接口无法达到代码的复用。这意味着,无论何时你需要修改某个行为,你必须得往下追踪并在每一个定义此行为的类中修改它,容易出错。
2. 模式定义:
策略模式:定义了算法族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
策略模式类图:
设计原则:
(1)找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
(2)针对接口编程,而不是针对实现编程。
其中这里的接口可以是java中定义的interface,也可以是abstract class。
(3)多用组合,少用继承。
3.代码实现:
FlyBehavior.java:
package net.pmpa.strategy;
public interface FlyBehavior {
public void fly();
}
FlyWithWings.java:
package net.pmpa.strategy;
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I can fly with wings!!");
}
}
FlyRocketPowered.java:
package net.pmpa.strategy;
public class FlyRocketPowered implements FlyBehavior {
public void fly() {
System.out.println("I'm flying with a rocket");
}
}
FlyNoWay.java:
package net.pmpa.strategy;
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("I can't fly!!");
}
}
QuackBehavior.java:
package net.pmpa.strategy;
public interface QuackBehavior {
public void quack();
}
Quack.java:
package net.pmpa.strategy;
public class Quack implements QuackBehavior {
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("Quack!!");
}
}
Squeak.java:
package net.pmpa.strategy;
public class Squeak implements QuackBehavior {
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("Squeak!!");
}
}
MuteQuack.java:
package net.pmpa.strategy;
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("I can't quack!!");
}
}
Duck.java:
package net.pmpa.strategy;
public abstract class Duck {
FlyBehavior flybehavior;
QuackBehavior quackbehavior;
public void swim(){
System.out.println("All ducks can swim!!");
}
public abstract void display();
public void performQuack() //委托子类实现
{
quackbehavior.quack();
}
public void performFly()
{
flybehavior.fly();
}
public void setFlybehavior(FlyBehavior flybehavior) { //可以动态设定duck的行为,先定义一个FlyBehavior的对象,再赋予该duck
this.flybehavior = flybehavior;
}
public void setQuackbehavior(QuackBehavior quackbehavior) {
this.quackbehavior = quackbehavior;
}
}
MallardDuck.java:
package net.pmpa.strategy;
public class MallardDuck extends Duck {
public MallardDuck()
{
flybehavior = new FlyWithWings();
quackbehavior = new Quack();
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("I'm a Mallard Duck!!");
}
}
RedHeadDuck.java:
package net.pmpa.strategy;
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");
}
}
RubberDuck.java:
package net.pmpa.strategy;
public class RubberDuck extends Duck {
public RubberDuck() {
flybehavior = new FlyNoWay();
quackbehavior = new Squeak();
}
public void display() {
System.out.println("I'm a rubber duckie");
}
}
DecoyDuck.java:
package net.pmpa.strategy;
public class DecoyDuck extends Duck {
public DecoyDuck() {
setFlybehavior(new FlyNoWay());
setQuackbehavior(new MuteQuack());
}
public void display() {
System.out.println("I'm a duck Decoy");
}
}
ModelDuck.java:
package net.pmpa.strategy;
public class ModelDuck extends Duck {
public ModelDuck() {
flybehavior = new FlyNoWay();
quackbehavior = new Quack();
}
public void display() {
System.out.println("I'm a model duck");
}
}
MiniDuckSimulator.java 测试类:
package net.pmpa.strategy;
public class MiniDuckSimulator {
public static void main(String[] args) {
MallardDuck mallard = new MallardDuck();
RubberDuck rubberDuckie = new RubberDuck();
DecoyDuck decoy = new DecoyDuck();
Duck model = new ModelDuck();
mallard.performQuack();
rubberDuckie.performQuack();
decoy.performQuack();
model.performFly();
model.setFlybehavior(new FlyRocketPowered()); //动态行为设定
model.performFly();
}
}