HeadFirst设计模式之策略模式

最近看完了《HeadFirst设计模式》这本书,想趁着这个机会写点东西总结总结,因此准备开始从今天开始将各种设计模式捋一遍,记录下来为有需要的同学当做参考 。闲话少叙,今天首先来说一下策略模式 。首先给出策略模式的定义:**策略模式定义了算法蔟,分别封装起来,让他们之间可以相互替换,此模式让算法的变化独立于使用算法的客户 。**假设你想开发一个模拟鸭子的游戏,其中有各式各样的鸭子,鸭子拥有各种行为,因此你设计一个鸭子的超类,然后各种鸭子继承此超类 。
public abstract class Duck {abstract public void quak(); //这些方法为鸭子的各种行为,包括游泳、呱呱叫等abstract public void swim();abstract public void display();}class MallardDuck extends Duck{void display(){//....实现该鸭子为绿头鸭,展示起来头为绿色的}}class RedHeadDuck extends Duck{void display(){//....实现该鸭子是红头的,展示起来为红色}}
现在你的鸭子功能模拟器的功能增加了,现在需要鸭子会飞,因此你可能会想到在抽象基类加一个fly()方法 。
public abstract class Duck {abstract public void quak(); //这些方法为鸭子的各种行为,包括游泳、呱呱叫等abstract public void swim();abstract public void display();abstract public void fly(); //新增飞翔行为}
此时抽象基类继承的问题就暴露出来了,因为各个鸭子都继承了基类的抽象方法,假设现在有一只橡皮鸭子也继承了该基类,如下所示 。
/***各个子类都要实现抽象基类中的抽象方法,表示为自己本身的实现 。*/class RubberDuck extends Duck{ void display(){};void swim(){};void quak(){};void fly(){// 可以对其进行空实现,什么也不做};}
很明显橡皮鸭子是不会飞的,但是它仍然要实现你定义在抽象基类中的方法 。当然你可以在fly()方法中对其进行空实现,什么也不做 。
但是如果以后加入其他的鸭子,比如说诱饵鸭,这是一种假鸭子不回飞也不会叫,你就需要对其中的多个方法进行空实现 。

HeadFirst设计模式之策略模式

文章插图
class DecoyDuck extends Duck{ void display(){};void swim(){};void quak(){// 覆盖,但是空实现};void fly(){// 可以对其进行空实现,什么也不做// 覆盖,但是空实现};}
但是如果我们以后要开发出越来越多种类的鸭子怎么办呢,这些新鸭子可能会有一些新的行为,如果我们每次向基类里添加一个新的行为,那我们都需要去所有这个基类的继承子类中去实现新的行为方法,而有的行为并不是所有鸭子共有的,这种每次新增行为都大量去更改已有代码显然是不能接受的 。
那如果把飞行行为和叫声行为抽离出来成单独的接口是否可行呢?
public abstract class Duck {abstract public void swim();abstract public void display();}public interface Quackable{void quack();}public interface Flyable{void fly();}class RedHeadDuck extends Duck implements Quackable,Flyable{void fly(){};void quack(){};void display(){};void swim(){};}
虽然这可以解决不再有会飞的鸭子这种现象,但是其中很多的方法比如说fly()方法,需要重复写很多代码,因为鸭子的飞行差不多都一样,如果我们有几十个实现子类,那么需要写几十次飞行方法,造成大量的重复代码 。
我们的业务可能随时应对变化,因此要尽量将自己的代码能够应对变化性,在变化的时候能够尽量修改较少的代码 。此时就对应到了设计模式的一个***设计原则,***我称为此原则为动静分离:**找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要辩护的代码混在一起 。**也就是说将变化的代码抽离出来和不经常变化的代码分离开,这样就能在变化的时候尽量少的影响其他代码 。