本篇博客来源于 Head First (原创总结)
策略模式 :定义了算法类,分别封装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。
Joe在公司上班,要设计一款鸭子游戏,游戏中会出现各种类型的鸭子拥有不同的行为,(游泳,呱呱叫、飞...) ,Joe很容易的就想到了 设计一个superClass , 让各种鸭子集成这个超类就好了。
1、现在有新的需求,为了击败竞争对手,项目经理让Joe设计一只会飞的鸭子。 Joe一想这有什么难的,一分钟搞定。于是在超类里面 加了一个 fly()方法; 第二天可怕的事情发生了,游戏中满屏的木头鸭子飞来飞去。原来在父类中加入fly()会导致所有的子类鸭子都具有会飞的能力。
2、Joe又想到了 重写父类中 fly() 方法, 木头鸭重写
fly(){
//什么都不做
}
但是以后如果有橡皮鸭 同样也不会飞,也不会叫,要覆盖所有的方法吗?,所以使用继承 会牵一发而栋全身,造成其他鸭子不想要的改变,另外也很难知道所有鸭子的行为,运行时的
行为不容易改变等问题。
3、Joe又想到了接口 把超类中的 fly()取出来放在 FlyInterface里面,只有会飞的鸭子才去实现这个接口,也可以设计一个QuackInterface接口,因为不是所有的鸭子都会叫。
但大牛说这是一个超级笨的方法,你没发现 这么一来重复的代码会变得更多吗? 如果你认为覆盖几个方法就算差劲,那么 让你稍微改变一下48个Duck的子类的飞行行为,你又怎么说
如果你是Joe,你怎么办???
把问题归零
接口看似解决了问题,但是接口不具有实现代码的能力,所有继承接口无法达到代码的复用,这意味着:无论何时你需要修改某个行为,你必须得往下追踪并在每一个定义此行为的类中去修改它。幸运的是有一个设计模式,恰好适用此状况。
把会变得部分取出来,并封装起来。而不去影响不需要变化的部分,好的,是时候把鸭子的行为 从Duck类中取出来了。
4、现在有两个接口,FlyInterface 和 QuackInterface 负责实现具体的行为
public interface FlyInterface {
abstract void fly();
}
public interface QuackInterface {
abstract void quack();
}
这样设计,这些行为已经与鸭子类无关了
首先在Duck中加入 两个实力变量
FlyInterface 、
QuackInterface
每只鸭子对象 都会动态的设置这些变量以在运行时引用正确的行为
每只鸭子对象 都会动态的设置这些变量以在运行时引用正确的行为
public abstract class Duck {
FlyInterface flyInterface;
QuackInterface quackInterface;
abstract void disPlay();
public void swiming(){
System.out.println("是鸭子都会游泳");
}
public void performFly(){
if(flyInterface !=null)
flyInterface.fly();
}
public void performQuack(){
if(quackInterface!=null)
quackInterface.quack();
}
public void setFlyBehave(FlyInterface flyInterface){
this.flyInterface = flyInterface;
}
public void setQuackBehace(QuackInterface quackInterface){
this.quackInterface = quackInterface;
}
}
下面我们暂定义 4种行为 分别去 继承 FlyInterface 、 QuackInterface 接口 会飞、不会飞、会叫、不会叫四种行为
public class FlyDuck implements FlyInterface{
public void fly() {
System.out.println("我会飞");
}
}
public class NotFlyDuck implements FlyInterface{
public void fly() {
System.out.println("我不会飞");
}
}
public class Quack implements QuackInterface{
public void quack() {
System.out.println("我会叫");
}
}
public class NotQuack implements QuackInterface{
public void quack() {
System.out.println("我不会叫");
}
}
下面我想 实现一个会飞会叫的野鸭子
public class MallardDuck extends Duck {
public MallardDuck(){
this.flyInterface = new FlyDuck();
this.quackInterface = new Quack();
}
void disPlay() {
System.out.println("我是绿头鸭");
}
}
Test类
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
MallardDuck mallardDuck = new MallardDuck();
mallardDuck.performFly();
mallardDuck.performQuack();
System.out.println();
mallardDuck.setFlyBehave(new NotFlyDuck()); 动态的去赋予鸭子行为
mallardDuck.setQuackBehace(new NotQuack());
mallardDuck.performFly();
mallardDuck.performQuack();
}
}
总结 :一种行为相当于一种算法,我们在实力类中根据具体情况去组装 相应的算法(行为),及灵活又可以达到代码的复用 。