设计模式之策略模式

策略模式

什么是策略模式?

策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

策略模式涉及的OO涉及原则

  • 将代码中变化的部分与不变化的部分分离并封装,以达到复用的效果
  • 面向接口编程,而不是面向实现编程
  • 使用组合,而不是用继承

策略模式案例

现有一个关于鸭子的系统,原有系统的设计如下:
这里写图片描述
现有一个需求,鸭子可以在屏幕上乱飞。看到这个需求,我的本能反应:Are you kidding me?!这么简单,哈哈,直接在父类Duck中添加fly()方法不就行了,so easy。所以系统的设计修改如下:
这里写图片描述
好烦,项目经理又改需求了,公司的业务拓展了,现在也卖:玩具鸭子…,好吧,又要改设计了,不过这也难不倒我,直接创建一个继承于Duck类的玩具鸭子就好了呀。唉,我一直在承受我这个年纪不该有的机智和帅气,我好累!!! ^V^。so,设计又变成了下面这个样子:
这里写图片描述
代码改完的第二天,项目经理走到我的办公桌前,”小李,你来一下我办公室。”“哈哈,难道我帅气的外表已经掩盖不住我盖世的才华了吗!嘻嘻,要加薪了,马上就要走上人生巅峰,赢取白富美了。哇,早就知道这天不会太远,但是好突然,还没准备好,肿么办。嗯,就这么决定了,明天就娶个白富美,哈哈^V^…”。”小李,什么情况,公司系统的玩具鸭子也会飞,是什么情况,侬脑子坏特啦!!!”。没错,重要的事情说三遍:侬脑子歪特啦!!!,侬脑子歪特啦!!!,侬脑子歪特啦!!!。腹诽:”侬脑子歪特啦!!! 侬全家脑子都歪特啦”。额,圈错了重点……重点好像是:玩具鸭子会飞。握草,玩具鸭子会飞,玩具鸭子会飞,玩具鸭子会飞,肿么办?! Fuck,又要该设计! 我想唱首歌,想问天问大地,我做错了什么。Ok,自己作的孽,自己来承担后果,改吧…灵机一动,ToyDuck覆盖Duck中的fly()方法,且fly()方法没有具体实现即可。所以,设计图成了这样:
这里写图片描述
但是这样设计好像有点问题?具体是什么问题呢?如果说,还有其他类别不会飞的鸭子,难道每次创建新类,都要重写fly()方法,最重要的是,重写的fly()方法没有任何实现,好傻的设计…好吧,重点不是fly()方法没有任何实现,而是:每新创建一个类,都要覆盖方法,ToyDuck中的fly方法,没有复用…淡淡的忧桑。谁能告诉我,该怎么设计,who can tell me?
看到了这里,相信大家都已经有思路了。今天总结的是:策略模式。so,答案就是:策略模式。注意:每个女人(设计模式)的背后都有几个男人(OO设计原则)默默的支持。是哪些男人(OO涉设计模式)呢?
- 将代码中变化的部分与不变化的部分分离并封装,以达到复用的效果
- 面向接口编程,而不是面向实现编程
- 使用组合,而不是用继承
套一套这三点OO设计原则,设计可以改变如下:
这个案例中有哪些是可变的?
- 叫声:真实的鸭子的叫声是:嘎嘎;玩具鸭子是:吱吱;其他的鸭子可能是其他的叫声
- 飞:真实的鸭子会飞;玩具鸭不会飞
如果这两个行为都在Duck类中,已经写好实现,那真是一个糟糕的设计。
第一个OO原则:将变化的与不变化的分离并封装。
分离出来,那么封装成什么,类么?很明显,抽象成类不合适,叫与飞只是一个行为。
然后又根据第二个OO原则:面向接口编程。
自然而然,这两个行为可以分离,封装成接口:Quack、Flyable。
设计如下:
这里写图片描述
那么设计现在已经被改的面目全非。但是这样的设计,扩展性很好。
最后设计的代码(Java)如下:

public abstract class Duck {
    String name;
    Quack quack;
    Flyable flyable;

    public abstract void display();
    public void performQuack(){
        quack.quack();
    }
    public void performFly() {
        flyable.fly();
    }
}

public class DomesticDuck extend Duck {
    public DomestisDuck(Quack quack, Flyable flyable) {
        this.quack = quack;
        this.flyable = flyable;
    }
    public void display(){
        //方法体
    }
}

public class WildDuck extend Duck {
    public WildDuck(Quack quack, Flyable flyable) {
        this.quack = quack;
        this.flyable = flyable;
    }
    public void display(){
        //方法体
    }
}

public class ToyDuck extend Duck {
    public ToyDuck(Quack quack, Flyable flyable) {
        this.quack = quack;
        this.flyable = flyable;
    }
    public void display(){
        //方法体
    }
}

public interface Quack {
    void quack();
}

//嘎嘎叫
public class GaGaQuack implements Quack{
    public void quack() {
        System.out.println("gaga...");
    }
}

//吱吱叫
public class ZhiZhiQuack implements Quack {
    public void quack() {
        System.out.println("zhizhi...");
    }
}

public interface Flyable {
    void flyable();
}

//会飞
public class CanFly implements Flyable{
    public void flyable() {
        System.out.println("can fly...");
    }
}

//不会飞
public class CanNotFly implements Flyable{
    public void flyable() {
        System.out.println("can not fly...");
    }
}

public class Test {
    public static void main(String[] args) {
        DomesticDuck duck1 = new DomesticDuck(new GaGaQuack(), new CanFly());
        WildDuck duck2 = new WildDuck(new GaGaQuack(), new CanFly());
        ToyDuck duck3 = new ToyDuck(new ZhiZhiQuack(), new CanNotFly());
        duck1.performQuack();
        duck1.performFly();
        duck2.performQuack();
        duck2.performFly();
        duck3.performQuack();
        duck3.performFly();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值