现在我们设计一个情景:我们想生产一些鸭子,根据公司生产规则,先要产生
一个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();
}
....
....
....
}
这样写我们看看会差生什么结果:
现在我们想生产一个绿头鸭,这个鸭子可以叫,也可以飞。我们需要
实现一次
(仅仅一次哦~)FlyBehavior
和QuackBehavior
接口:
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只小黄鸭(能叫不能飞)。这也难不
倒你呀!
先按照小黄鸭的规则实现
FlyBehavior
和QuackBehavior
接口,然后仿照上面的代码生产。这个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-设计模式》一书,作者总结的内容不到书内容精彩十分之一,还望大家多读原著.