设计模式-策略模式

11 篇文章 0 订阅
2 篇文章 0 订阅
现在我们设计一个情景:我们想生产一些鸭子,根据公司生产规则,先要产生
一个Duck超类。用Duck超类来创建鸭子。Duck类如下:
class abstract Duck(){
    public void swim(){
    //所有鸭子都具有游泳的功能
    }
    //每个鸭子都有自己的外观,所以用抽象方法
    public abstract void display();
}
现在我们想让鸭子能飞。。。。

这样做会实现:在Duck超类里添加fly()方法,这样生产出来的鸭子不就能飞了么!
所以我们这样定义超类:

class abstract Duck(){
    public void swim(){
    //所有鸭子都具有游泳的功能
    }
    public void fly(){
    //让鸭子飞起来
    }
    //每个鸭子都有自己的外观,所以用抽象方法
    public abstract void display();
}
如果我们想让鸭子叫,“理所应当” 我们可以这样写:
class abstract Duck(){
    public void swim(){
    //所有鸭子都具有游泳的功能
    }
    public void fly(){
    //让鸭子飞起来
    }
    public void quack(){
    //鸭子会叫了
    }
    //每个鸭子都有自己的外观,所以用抽象方法
    public abstract void display();
}

如你所愿,用Duck类产出来的鸭子即会飞,也会叫了。


但是!意想不到的事情发生了。如果公司想要生产一个橡皮鸭子,结果,橡皮
鸭子飞了起来。(多诡异)当然还有更诡异的事情:橡皮鸭子不光会飞,还会叫!!

哎呀~~~

遇到问题了,想解决办法吧。

可能你觉得这样做就可以解决了:把fly()quack()也定义成抽象函数,如下:

class abstract Duck(){
    public void swim(){
    //所有鸭子都具有游泳的功能
    }
    public abstract void fly();
    public abstract void quack();
    //每个鸭子都有自己的外观,所以用抽象方法
    public abstract void display();
}

这样我们生产鸭子的时候复写fly()quack()方法:

class RubberDuck extends Duck{
    public void fly(){
    //橡皮鸭子不会飞,所以fly()就什么都不做了
    }
    public void quack(){
    //橡皮鸭不会叫,所以也什么都不用做
    }
    public void display(){
      System.out.println("我是橡皮鸭子");
    }
}
这样我们想生产什么鸭子就可以生产什么鸭子了

你不会感觉这就万事大吉了吗?

你不觉得这样每生产一个鸭子就要重写这两个代码。我们生产的鸭子各不相似的话作用还
比较大,如果我们就生产三种鸭子,但是需要生产1000000....个鸭子,你每个类都需要重写
fly()quack()两个函数.

你很喜欢写代码是吧…

也许你想到的不是上面的想法,来,看看是不是下面的想法:

public interface FlyBehavior{
    public void fly();
}

public interface QuackBehavior{
    public void quack();
}

public class RubberDuck extends Duck implements FlyBehavior, QuackBehavior{
    .....
    .....
}

如果你觉得这样写很聪明,的确,你聪明的把行为部分提炼出来改成了接口,但是与上
一个方法做写的代码量有多少差别呢???

来来来,你离真理就差一步之遥了……

我们把上面的方法在进行一次修改……
public interface FlyBehavior{
    public void fly();
}

public interface QuackBehavior{
    public void quack();
}

public class FlyNoWay implements FlyBehavior{
    public void fly(){
        System.out.println("I can't fly");
    }
}

public class Quack implements QuackBehavior{
    public void quack(){
        System.out.println("I can't quack");
    }
}
然后我们把Duck类改进下:
public class Duck{

    private FlyBehavior flybehavior;
    private QuackBehavior quackbehavior;

    public void swim(){
    //所有鸭子都具有游泳的功能
    }

    //表现飞
    public void proformFly(){
        flybehavior.fly();
    }

    //表现叫
    public void proformQuack(){
        quackbehavior.quack();
    }

    //每个鸭子都有自己的外观,所以用抽象方法
    public abstract void display();
}
然后我们开始产鸭子了…..
public class RubberDuck extends Duck{

    public RubberDuck(){
        flybehavior = new FlyNoWay();
        quackbehavor = new Quack();
    }

    ....
    ....
    ....
}
这样写我们看看会差生什么结果:

现在我们想生产一个绿头鸭,这个鸭子可以叫,也可以飞。我们需要
实现一次(仅仅一次哦~)FlyBehaviorQuackBehavior接口:

public class FlyWithWings implements FlyBehavior{
    public void fly(){
        System.out.println("I can fly with wings");
    }
}

public class Quack implements QuackBehavior{
    public void quack(){
        System.out.println("I can  quack");
    }
}

然后该生产绿头鸭了。。。

public class GreenDuck extends Duck{

    public GreenDuck(){
        flybehavior = new FlyWithWings();
        quackbehavor = new Quack();
    }

    ....
    ....
    ....
}

但是,我有一个很挑剔的boss,boss想生产出10000只小黄鸭(能叫不能飞)。这也难不
倒你呀!

  • 先按照小黄鸭的规则实现FlyBehaviorQuackBehavior接口,然后仿照上面的代码生产。

  • 这个boss又想让我生产100000只小绿鸭(能叫不能飞),这样更好啊:直接重用小黄鸭实
    现的两个行为的类就好了….

注意啦!!!现在我们根据上面的现象提出两个设计模式的原则(设计模式有很多原则)

原则1:找出应用中可能需要变化之处,把他们独立出来,不和那些不需要变化的代码混在一起
原则2:针对接口编程,而不是针对实现编程。


等等…..(下面的要好好的体会)

刚刚这两个原则不是说不针对实现编程吗?那这段代码:

public GreenDuck(){
    flybehavior = new FlyWithWings();
    quackbehavor = new Quack();
}

不是在构造函数里进行了实现操作了么、、、这不是不灵活了么!!!!

好吧,被你发现了….这样做确实还不够灵活,不过既然被你发现了,我也不能把最后一个
技能藏着掖着了:我们可以在Duck类里写一个set函数:
public void setFlyBehavior(FlyBehavior flybehavior){
this.flybehavior = flybehavior;
}

public void setQuackBehavior(QuackBehavior quackbehavior){
    this.quackbehavior = quackbehavior;
}

好吧,这样变得多灵活,想改变行为就改变行为!

好吧,我已经把所有的技能都教给你了,你该满足了吧 ~.~


既然你已经学会了这个神奇的技能,那么你应该知道这个技能叫什么吧!

当当当当~~~

恭喜您,学会了第一个设计模式: 策略模式

现在我给您一个高达上的定义(如果你想让你的朋友对你刮目相看,请用这个定义)

策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换, 此模式让算法的变化独立于使用算法的客户(下面的定义可以提高b格)
The strategy Parttern: define a family of algorithms, encapsulates
each ones, and make them interchangeable, strategy lets the algorithm
vary independently from clients that use is.


下面是`策略模式`的类图

策略模式类图

下面是整个项目的代码(可以忽略)
public abstract class Duck{

    public FlyBehavior flybehavior;
    public QuackBehavior quackbehavior;

    public Duck(){
    System.out.println("Duck is constructing...");
    }

    public abstract void display();

    public void proformQuack(){
    quackbehavior.quack();
    }

    public void proformFly(){
    flybehavior.fly();
    }
}

public interface FlyBehavior{
    public void fly();
}

public interface QuackBehavior{
    public void quack();
}

public class Quack implements QuackBehavior{
    public void quack(){
    System.out.println("quack...");
    }
}

public class FlyWithWings implements FlyBehavior{

    public void fly(){
    System.out.println("fly with wings......");
    }
}

public class DuckTestFirst extends Duck{
    public DuckTestFirst(){
    System.out.println("ducktestf is constructing...");
    flybehavior = new FlyWithWings();
    quackbehavior = new Quack();
    }

    public void display(){
    System.out.println("this is ducktestfirst....");
    }


}

public class Main{

    public static void main(String[] args){
            Duck duck =new DuckTestFirst();
            duck.proformFly();
            duck.proformQuack();
    }
}

谢谢观看,结束本节!
注:本文借鉴了《HeadFirst-设计模式》一书,作者总结的内容不到书内容精彩十分之一,还望大家多读原著.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值