第一次设计
所有鸭子都有共性,比如绿头鸭 红头鸭子,等等。所以我们建了一个超类Duck,即抽象类
因为每种鸭子叫的方式或者外观不一样,所以超类定义了三个抽象的方法, 叫、游泳、外观。
定义抽象类
public abstract class Duck {abstract void quack();abstract void swim();abstract void display();}
俩只鸭子子类
一只红头鸭子,一只橡皮鸭子。
public class RedheadDuck extends Duck {@Overridevoid quack() {}@Overridevoid swim() {}@Overridevoid display() {System.out.println("我是红色的");}}
public class RubberDuck extends Duck {@Overridevoid quack() {}@Overridevoid swim() {}@Overridevoid display() {System.out.println("外观是橡皮");}}
新需求:鸭子能飞
现在要鸭子能飞。
那么很好,我们只需这样,在超类上加一个fly行为不就行了?
public abstract class Duck {abstract void quack();abstract void swim();abstract void display();abstract void fly();}
暴露问题
那么问题来了,橡皮鸭子可不会飞啊,如果再加一个木头鸭呢?它可不会叫啊。
会发现,不同的鸭子我甚至根本不需要某些方法, 那么子类却要被强制实现该方法,尽管我可以不重写。
也就是说,我现在想要单独给某个鸭子加上个fly()!, 不影响其它已经存在的鸭子。
提出假象
既然如此,不如将fiy() 做成一个接口,哪个鸭子能飞,我就让它实现一下不就行了?
不建议这么做的理由:
1、假如鸭子有上千个行为,你是否要定义上千个接口呢?
2、违背初衷,目前超类的存在,它的代码复用价值已经不大了。
解决方案
从解决方案一中可以发现思路,既然抽出一个行为(比如fly)不行,那么干脆把鸭子的所有行为都抽象出来吧。
因为鸭子的行为一直是在变动的。为了不影响稳定的行为,那么干脆让它们分离开。
抽离出fly行为
public interface FlyBehavior {void fly();}
抽离出quack行为
public interface QuackBehavior {void quack();}
我让所有飞的行为,不论是挥着翅膀飞还是滑行着飞,还是不会飞,我都必须实现这个FlyBehavior这个接口
public class FlyWithWings implements FlyBehavior {@Overridepublic void fly() {System.out.println("我带着翅膀飞!");}}
public class FlyNoWay implements FlyBehavior {@Overridepublic void fly() {System.out.println("我不会飞!");}}
这个时候你会发现,凡是会飞的鸭子那么我就拿走 FlyWithWings这个类好了。
即使我在加几个飞的动作,也不会影响到已经存在的鸭子行为。
第二次设计
public abstract class Duck {FlyBehavior flyBehavior;QuackBehavior quackBehavior;public abstract void display();public void performFly(){flyBehavior.fly();}public void performQuack(){quackBehavior.quack();}public void setFlyBehavior(FlyBehavior flyBehavior) {this.flyBehavior = flyBehavior;}public void setQuackBehavior(QuackBehavior quackBehavior) {this.quackBehavior = quackBehavior;}}
红头鸭
public class RedheadDuck extends Duck{@Overridepublic void display() {System.out.println("我是红头鸭");}}
橡皮鸭
public class RubberDuck extends Duck{@Overridepublic void display() {System.out.println("我是橡皮鸭");}}
测试
红头鸭
public class Test {public static void main(String[] args) {Duck redHeadDuck = new RedheadDuck();redHeadDuck.display()redHeadDuck.setFlyBehavior(new FlyWithWings()); //给它一个fly行为 的实现类redHeadDuck.performFly();}}我是红头鸭我带着翅膀飞!
橡皮鸭
public class Test {public static void main(String[] args) {Duck rubberDuck = new RubberDuck();rubberDuck.display();rubberDuck.setFlyBehavior(new FlyNoWay()); //给它一个fly行为 的实现类rubberDuck.performFly();}}我是橡皮鸭我不会飞!
新增需求:再添加一个模型鸭子
我要求这个鸭子能飞,但是它没有翅膀。 很简单,再实现一次飞行的行为即可
public class ModelDuck extends Duck {@Overridepublic void display() {System.out.println("我是模型鸭子");}}
public class FlyRocketPowered implements FlyBehavior {@Overridepublic void fly() {System.out.println("我有火箭助推器!");}}
测试
public class Test {public static void main(String[] args) {ModelDuck modelDuck = new ModelDuck();modelDuck.display();modelDuck.setFlyBehavior(new FlyRocketPowered());modelDuck.performFly();}}我是模型鸭子我有火箭助推器!
小节:下定义
note: 策略模式: 定义算法族,分别封装起来,让它们直接可以动态替换,让算法的变化独立于使用算法的客户。借助了多态。
