(转)HeadFirst设计模式学习笔记(C#版):鸭子与策略(Strategy)模式
策略模式的设计原则如下:
1. 将应用中需要经常变化的代码独立出来,应和那些不需要经常变化的代码分开。
2. 应针对接口,而不是类进行编程。
3. 在类中应多用组合,少用继承。
例子:
我们要实现一个鸭子模拟器,这个鸭子模拟器由Duck类描述,而Duck类有如下4个行为:
1. display
2. swim
3. fly(飞)
4. quack(叫)
其中swim是所有鸭子都具有的特性,而且所有鸭子的这些特性都相同,因此,这个方法可以直接在Duck类中实现。display方法也是所有鸭子具有的特性,但随着鸭子的种类不同,display也有所不同,因此,display方法应为Duck类的抽象方法。fly和quack并不是所有鸭子的特性,如橡皮鸭子即不会飞,也不会叫。因此,可以将这两个方法看作是两个行为,可将每一个行为设计成一个接口。这样可以和Duck类完全脱离。因为,fly和quack与Duck一点关系都没有(别的东西也可能fly和quack),然后不同的fly和quack分别用实现相应接口的类表示。
下面是关于Duck的完整代码:
fly行为
// 飞行接口
public interface FlyBehavior
{
String fly();
}
// 飞
public class FlyWithWing : FlyBehavior
{
public String fly()
{
return "正在用翅膀飞行";
}
}
// 不飞
public class FlyNoWay : FlyBehavior
{
public String fly()
{
return "不会飞";
}
}
public interface FlyBehavior
{
String fly();
}
// 飞
public class FlyWithWing : FlyBehavior
{
public String fly()
{
return "正在用翅膀飞行";
}
}
// 不飞
public class FlyNoWay : FlyBehavior
{
public String fly()
{
return "不会飞";
}
}
quack行为
// 叫
public interface QuackBehavior
{
String quack();
}
// 嘎嘎叫
public class Quack : QuackBehavior
{
public String quack()
{
return "嘎嘎叫";
}
}
// 吱吱叫
public class Squeak : QuackBehavior
{
public String quack()
{
return "吱吱叫";
}
}
// 不叫
public class MuteQuack : QuackBehavior
{
public String quack()
{
return "不会叫";
}
}
public interface QuackBehavior
{
String quack();
}
// 嘎嘎叫
public class Quack : QuackBehavior
{
public String quack()
{
return "嘎嘎叫";
}
}
// 吱吱叫
public class Squeak : QuackBehavior
{
public String quack()
{
return "吱吱叫";
}
}
// 不叫
public class MuteQuack : QuackBehavior
{
public String quack()
{
return "不会叫";
}
}
实现Duck类
// 鸭子超类
public abstract class Duck
{
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
public Duck()
{
// 默认的行为
flyBehavior = new FlyWithWing();
quackBehavior = new Quack();
}
public String swim()
{
return "正在游泳";
}
public String performFly()
{
return flyBehavior.fly();
}
public String performQuack()
{
return quackBehavior.quack();
}
public void setFlyBehavior(FlyBehavior flyBehavior)
{
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior)
{
this.quackBehavior = quackBehavior;
}
public abstract String display();
}
public abstract class Duck
{
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
public Duck()
{
// 默认的行为
flyBehavior = new FlyWithWing();
quackBehavior = new Quack();
}
public String swim()
{
return "正在游泳";
}
public String performFly()
{
return flyBehavior.fly();
}
public String performQuack()
{
return quackBehavior.quack();
}
public void setFlyBehavior(FlyBehavior flyBehavior)
{
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior)
{
this.quackBehavior = quackBehavior;
}
public abstract String display();
}
建立不同的鸭子类
// 野鸭
public class MallardDuck : Duck
{
public override String display()
{
return "绿头鸭";
}
}
// 红头鸭
public class RedHeadDuck : Duck
{
public override String display()
{
return "红头鸭";
}
}
// 橡皮鸭
public class RubberDuck : Duck
{
public override String display()
{
return "橡皮鸭";
}
}
public class MallardDuck : Duck
{
public override String display()
{
return "绿头鸭";
}
}
// 红头鸭
public class RedHeadDuck : Duck
{
public override String display()
{
return "红头鸭";
}
}
// 橡皮鸭
public class RubberDuck : Duck
{
public override String display()
{
return "橡皮鸭";
}
}
接口与类的关系如下图
调用代码如下:
private void printMsg(Duck duck)
{
txtMsg.AppendText(duck.display());
txtMsg.AppendText(duck.performFly());
txtMsg.AppendText(duck.performQuack());
}
private void btnStrategy_Click(object sender, EventArgs e)
{
txtMsg.Clear();
Duck duck = new MallardDuck();
printMsg(duck);
txtMsg.AppendText("\r\n");
duck = new RedHeadDuck();
duck.setQuackBehavior(new Squeak());
printMsg(duck);
txtMsg.AppendText("\r\n");
duck = new RubberDuck();
duck.setFlyBehavior(new FlyNoWay());
duck.setQuackBehavior(new MuteQuack());
printMsg(duck);
txtMsg.AppendText(duck.swim());
txtMsg.AppendText("\r\n");
}
{
txtMsg.AppendText(duck.display());
txtMsg.AppendText(duck.performFly());
txtMsg.AppendText(duck.performQuack());
}
private void btnStrategy_Click(object sender, EventArgs e)
{
txtMsg.Clear();
Duck duck = new MallardDuck();
printMsg(duck);
txtMsg.AppendText("\r\n");
duck = new RedHeadDuck();
duck.setQuackBehavior(new Squeak());
printMsg(duck);
txtMsg.AppendText("\r\n");
duck = new RubberDuck();
duck.setFlyBehavior(new FlyNoWay());
duck.setQuackBehavior(new MuteQuack());
printMsg(duck);
txtMsg.AppendText(duck.swim());
txtMsg.AppendText("\r\n");
}
输出结果如下:
绿头鸭正在用翅膀飞行嘎嘎叫
红头鸭正在用翅膀飞行吱吱叫
橡皮鸭不会飞不会叫正在游泳
红头鸭正在用翅膀飞行吱吱叫
橡皮鸭不会飞不会叫正在游泳