当先锋百科网

首页 1 2 3 4 5 6 7

以前看过Head First设计模式这本书,时间长了温习下,顺便写下博客总结下:

我们先来看下这个例子:uml图如下,做了一个鸭子的游戏。有各种鸭子,可以游泳,叫,还有各种显示。因此做了一个Duck的父类,子类只有display不一样。

现在,需要定义一些会飞的鸭子,但是也有比如玩具鸭不会飞。那我们应该怎么实现呢?有几种方法

1. 如果我们在Duck中添加fly方法,那么所有的子类都会飞了。如果那个特定的子类不会飞,就需要那个子类实现fly这个方法,并且空实现。但是这样非常麻烦,而且我后面又要增加别的功能,比如不会叫的鸭,就要在子类中把quack这个方法给空实现了,才行。所以这不是种好方法。而且代码在多个子类中重复

2. 还有一种方法我们定义两个interface 一个 Flyable 一个Quackable。然后在各个子类中自己实现。但是这样的话,重复代码会非常多。

3. 因此最好的方法是我们自己定义两个行为类,一个FlyBehavior 一个QuackBehavior 这两个类是Interface。然后在Duck中定义两个该Interface的对象,并且可以定义接口,动态添加行为。

public abstract class Duck {
	FlyBehavior flyBehavior;//在父类中定义了两个行为类
	QuackBehavior quackBehavior;
	public Duck() {}
	public abstract void display();
	public void performFly() {
		flyBehavior.fly();
	}
	public void performQuack() {
		quackBehavior.quack();//委托行为类
	}
	public void swim() {
		System.out.println("All ducks swim")
	}
}

public class MallardDuck extends Duck {
	public MallardDuck() {
		quackBehavior = new Quack();//针对接口编程,这里接口就是统一的父类或者Interface
		flyBehavior = new FlyWithWings();
	}
	public void display() {
		System.out.println("I'm real Mallard Duck.");
	}
}

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

public interface QuackBehavior {
	public void quack();
}

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

public class MuteQuack implements QuackBehavior {
	public void quack() {
		System.out.println("slience")
	}
}

测试类
public class MiniDuckSimulator {
	public static main(String[] args) {
		Duck mallard = new MallardDuck();
		mallard.performFly();
		mallard.performQuack();
	}
}


这里有几个设计原则:

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

2. 针对接口编程,而不是针对实现编程。

3. 多用组合,少用继承。


当然最后我们可以在Duck类中加入两个新的方法,就可以动态改变鸭子的行为:

public void setFlyBehavior(FlyBehavior fb) {
	flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
	quackBehavior = qb;
}

我们可以键一个新的FlyBehavior类型

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

这样我们就可以改变下测试类:

测试类
public class MiniDuckSimulator {
	public static main(String[] args) {
		Duck mallard = new MallardDuck();
		mallard.performQuack();		
		mallard.performFly();
		mallard.setFlyBehavior(new FlyRockedPowered());
		mallard.performFly();
	}
}
结果:
quack
I'm flying
I'm flying with a rocket!

最后我们再来看看uml图:


这种模式就是策略模式:

定义了算法族,分别封装起来(这里就是我们的行为类),让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。