设计模式系列-策略设计模式

走进设计模式

Posted by Mio4kon on 2015-04-15

策略设计模式定义

定义了算法簇,分别封装起来,让他们可以互相替换,此模式让算法独立于使用
他的客户.


ps : 去他大爷的定义,到底策略模式在什么情况使用呢?

鸭子可以叫,可以飞.但鸭子有很多样子的,有黄毛,绿毛,紫毛…
oop告诉我们,可以定义一个抽象的Duck类.然后具体实现就好辣嘛.

1
2
3
graph TD;
Duck-->黄毛鸭;
Duck-->绿毛鸭;

在duck中可以写fly()quack()方法.因为都是飞和叫.这样就一劳永逸了.

事实是残酷的,变化是一定滴..现在加入了玩具鸭,不能飞不能叫.还继承现在的duck类?可以吗?

可以,我们可以复写fly()quack()方法,然后空实现即可.
但是如果有能叫不能飞的鸭子呢?如果有能飞不能叫的鸭子呢?
难道要每一个都要单独复写?..蛋疼..


要不用接口吧?实现flybehavior接口和quackbehavior接口.不就可以解决问题了嘛.

日了狗了,一两个鸭子还好说,100个鸭子难道我要一个个的实现他的fly方法和quack方法?


新的问题:使用接口导致无法复用.

让我们把变化之处抽取来,然后面向接口编程(多态)


上面一句话到底啥意思啊.如何才能解决上面的问题???

代码伺候,代码看完估计也就懂了..

  1. 面向接口当然要有接口啦..
1
2
3
4
5
6
7
public interface FlyBehavior {
void fly();
}
public interface QuackBehavior {
void quack();
}
  1. 为了复用我们需要给接口实现一下.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class FlayNoWay implements FlyBehavior {
@Override
public void fly() {
ViewUtils.show ("我没法飞......");
}
}
public class FlayWithWings implements FlyBehavior{
@Override
public void fly() {
ViewUtils.show ("我在用翅膀飞....");
}
}
public class QuackGaGa implements QuackBehavior {
@Override
public void quack() {
ViewUtils.show ("我在嘎嘎叫..");
}
}
public class QuackZhiZhi implements QuackBehavior {
@Override
public void quack() {
ViewUtils.show ("我在吱吱叫...."); //玩具鸭就这么叫..
}
}
  1. 现在就可以写我们的父类Duck类了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class Duck {
public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;
public abstract void display();
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
}

display不用说,不同鸭子不同样子,肯定要子类实现.关键在于面向了接口,
我们无需知道flyquack(算法)的具体实现.

  1. 到了大显身手的时刻了.

真实的鸭子

1
2
3
4
5
6
7
8
9
10
11
public class TrueDuck extends Duck {
public TrueDuck() {
quackBehavior = new QuackGaGa (); //这种还是基于实现的定义 不好待改进
flyBehavior = new FlayWithWings ();
}
@Override
public void display() {
ViewUtils.show ("我是一只真鸭子..");
}
}I

玩具鸭子

1
2
3
4
5
6
7
8
9
10
11
public class ToyDuck extends Duck {
public ToyDuck() {
quackBehavior = new QuackZhiZhi();
flyBehavior = new FlayNoWay ();
}
@Override
public void display() {
ViewUtils.show ("我是一个玩具鸭子..");
}
}
  1. 最后展示一下试试
1
2
3
4
5
6
7
8
9
10
11
TrueDuck trueDuck = new TrueDuck ();
trueDuck.display ();
trueDuck.performFly ();
trueDuck.performQuack ();
ViewUtils.show ("====================");
ToyDuck toyDuck = new ToyDuck ();
toyDuck.display ();
toyDuck.performFly ();
toyDuck.performQuack ();
1
2
3
4
5
6
7
04-15 08:32:00.965 1744-1744/com.mio.template1 D/mio﹕ 我是一只真鸭子..
04-15 08:32:00.965 1744-1744/com.mio.template1 D/mio﹕ 我在用翅膀飞....
04-15 08:32:00.965 1744-1744/com.mio.template1 D/mio﹕ 我在嘎嘎叫..
04-15 08:32:00.965 1744-1744/com.mio.template1 D/mio﹕ ====================
04-15 08:32:00.965 1744-1744/com.mio.template1 D/mio﹕ 我是一个玩具鸭子..
04-15 08:32:00.965 1744-1744/com.mio.template1 D/mio﹕ 我没法飞......
04-15 08:32:00.965 1744-1744/com.mio.template1 D/mio﹕ 我在吱吱叫....

终于问题解决.我们即解决了新鸭子品种导致的Duck类的频繁变化,
也复用了常用的方法(可以飞,不可飞,呱呱叫,嘎嘎叫),再看看上面的定义.
yeah,you got it!

桥豆麻袋,还有一个问题,要是我用了一些方法使玩具鸭飞了咋办?
比如用了火箭助飞器?

简单的改造下就可以实现了.又提高了扩展性.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract class Duck {
public FlyBehavior flyBehavior;
public QuackBehavior quackBehavior;
public abstract void display();
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
>>==
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
==<<
}

在定义一个飞行的实现方法(算法)

1
2
3
4
5
6
public class FlyByRocket implements FlyBehavior {
@Override
public void fly() {
ViewUtils.show ("我用火箭飞起来了!!");
}
}

看看效果:

1
2
3
4
5
6
7
8
9
ToyDuck toyDuckByRocket = new ToyDuck ();
toyDuckByRocket.display ();
toyDuckByRocket.setFlyBehavior (new FlyByRocket ());
toyDuckByRocket.performFly ();
toyDuckByRocket.performQuack ();
04-15 08:44:48.413 4910-4910/com.mio.template1 D/mio﹕ 我是一个玩具鸭子..
04-15 08:44:48.413 4910-4910/com.mio.template1 D/mio﹕ 我用火箭飞起来了!!
04-15 08:44:48.413 4910-4910/com.mio.template1 D/mio﹕ 我在吱吱叫....