根据Head First一书整理示例和代码
UML类图介绍:
设计原则:
1、找出系统中需要变化的属性/变量,并将它们封装起来,区别于不需要变化的部分。
2、针对接口编程,抽象操作、行为,不针对具体实现编程。
策略模式:
策略设计模式是一种行为设计模式。当在处理一个事务时,有多种处理方式,并且需要在运行时决定使哪一种具体实现时,就会使用策略模式。
要求:
有一群十分特殊的鸭子,他们有的会飞,有的会叫,有的既会飞又会叫,且飞的款式和叫的方法各有不同,在鸭子们的行为能够改变。请设计满足这些需求的类图。
分析:
将对象与行为分离,使得他们在一定程度上能够自由组合。具体的飞行与叫的实现交给非鸭子的类去实现,仅仅抽象出飞行与叫的接口。
UML类图:
其中,Duck为鸭子超类,它有ReadHeadDuck与MallardDuck两个子类,这两个子类都有各自的飞行方式与叫唤方式。Duck中包含两个接口类型的成员变量。
Flyable与Quackable是飞行与叫两种行为的接口,FlyWithWings、FlyWithHands、Quack、MuteQuack分别是实现了Flyable与Quackable的具体类。
进一步地,如果在具体鸭子类的构造函数/公共方法中提供参数可以传入实现了Flyable与Quackable的具体类,那么在运行过程中即可改变鸭子不同的飞行方式与叫唤方式,甚至鸭子可以不用关心对方是谁。比如,对方可以是实现了飞行接口的人类..
代码实现与HeadFirst一书略有不同,相对而言我的代码拓展性稍微强一些。如果在具体鸭子类中增加改变飞行/叫成员变量的方法,那么在运行过程中可动态调整行为了,除了红头鸭设置了set方法,其他鸭子我只在父类构造方法中指定了duck 的行为。
UML对应的java代码(ComDucks是后来添加上去的,这是一类不会飞也不会叫的鸭子):
Duck超类:
public abstract class Duck {
public Flyable duckFly;
public Quackable duckQuack;
public Duck(){
this.duckQuack = null;
this.duckFly = null;
System.out.println("我只是一只小鸭子,暂时还不会飞、不会叫..\n");
}
public Duck(Flyable flyable, Quackable quackable){
this.duckFly = flyable;
this.duckQuack = quackable;
}
public void performFly(){
if (this.duckFly!=null)
duckFly.fly();
}
public void performQuack(){
if (this.duckQuack!=null)
duckQuack.quack();
}
public void disp(){
if (this.duckFly!=null)
this.performFly();
if (this.duckQuack!=null)
this.performQuack();
}
}
public interface Flyable {
public void fly();
}
public interface Quackable {
public void quack();
}
public class FlyWithHands implements Flyable{
@Override
public void fly() {
System.out.println("用双手飞行~");
}
}
public class FlyWithWings implements Flyable {
@Override
public void fly() {
System.out.println("用翅膀飞行~");
}
}
public class Quack implements Quackable{
@Override
public void quack() {
System.out.println("嘎嘎叫\n");
}
}
public class MuteQuack implements Quackable{
@Override
public void quack() {
System.out.println("不会叫,可笑..\n");
}
}
public class ComDuck extends Duck{
public ComDuck(){
super();
this.disp();
}
}
public class MallardDuck extends Duck{
private String name;
public MallardDuck(){
super(new FlyWithHands(), new MuteQuack()); //子类调用父类带参构造方法
this.setName();
this.perform();
}
public void setName() {
this.name = "绿头鸭";
}
public void perform(){
System.out.println("我是一只"+this.name);
this.disp();
}
}
public class ReadHeadDuck extends Duck{
private String name;
public ReadHeadDuck(){
super(new FlyWithWings(), new Quack()); //子类调用父类带参构造方法
this.setName();
this.perform();
}
public void setName() {
this.name = "红头鸭";
}
public void perform(){
System.out.println("我是一只"+this.name);
this.disp();
}
}
main方法:
public class TestClass {
public static void main(String[] args) {
ComDuck comDuck = new ComDuck();
MallardDuck mallardDuck = new MallardDuck();
ReadHeadDuck readHeadDuck = new ReadHeadDuck();
System.out.println("红头鸭开始变异..");
//动态改变红头鸭的行为
readHeadDuck.setFly(new FlyWithHands());
readHeadDuck.setQuack(new MuteQuack());
readHeadDuck.perform();
}
}
测试输出:
欢迎大家批评指正。
Reference
《Head First 设计模式》