用一个鸭子模拟游戏为例子,开始我们的设计模式学习之旅。
首先,我们需要设计各种鸭子的父类,包含有鸭子的共同特征和行为:
Duck
quack()
swim()
display()
.... //鸭子的其他行为特征
后来,PM(产品经理)需要鸭子具有飞行的行为,于是我们觉得很自然得让父类Duck加入了fly()方法, 子类通过继承父类,就都具有了飞行的行为。
问题来了....
PM发现, 游戏中的玩具橡皮鸭也飞了起来..... 这可真是雷人啊。
于是,可怜的我们就必须要重新设计。我们想到了在父类中fly()方法不做任何实现, 由子类去各自实现自己的fly行为, 比如橡皮鸭的fly()就什么都不做。
但是,如果仔细想想,以后不断新增鸭子的种类, 我们要不断去实现和覆盖fly方法, 这样真是太悲催了....
该怎么办?
我们受到启发,想到必须要把这些fly特殊行为从Duck类中分离出来,建立一组新类来实现具体的行为。 这一组新类由fly行为类型的接口来实现。
OK, 我们设计了飞行行为的接口:
FlyBehavior
我们可以针对这个接口实现不同的飞行类, 比如:FlyWithWings(真实的翅膀飞行), FlyNoWay(不会飞,比如橡皮鸭)
这样,我们的鸭子父类代码可以如下:
public abstract class Duck{
FlyBehavior flyBehavior;
public Duck(){
}
public abstract void display();
public void performFly(){
flyBehavior.fly();
}
}
FlyBehavior接口的实现代码:
public interface FlyBehavior{
public void fly();
}
public class FlyWithWings implements FylBehavior{
public void fly()
{
........
}
}
public class FlyNoWay implements FlyBehavior //不会飞
{
public void fly()
{
......
}
}
现在的设计已经有了很大进步了, 但是我们还需要做到能够动态绑定具体的行为接口。于是,我们在Duck父类中,加入了新方法
public void setFlyBehavior(FlyBehavior fb)
{
flyBehavior = fb;
}
这样,我们可以动态的切换鸭子具体行为了,太好了 哈哈
上述实现过程中, 我们把多个类组合起来使用,灵活性更强,耦合性也相对弱了很多。
做完上述设计,我们已经学会了第一个设计模式:策略模式(Strategy Pattern)
策略模式的定义: 它定义了算法族,分别封装起来,让他们之间可以相互替换,此模式算法的变化独立于使用算法的客户。
在软件开发上有个不变的真理: change
设计原则:
1. 找出应用中可能需要变化之处, 把他们独立出来, 别和不需要变化的代码混在一起。
2. 针对接口编程, 而不是针对实现编程。
3.多用组合,少用继承。