A stray ant can only move by itself

Head Firsh 设计模式-策略模式

使用模式的最好方式:—经验复用

把模式装进脑子里,然后在你的设计和已有的应用中, 寻找何处可以使用他们。

Duck 鸭子超类, 所有的鸭子继承该类

1
2
3
quack(); // 呱呱叫
swim();//游泳
display(); //外观

现在让鸭子飞起来?!!!
fly();
导致所有的鸭子都能飞起来。。。。
当设计“维护”时, 为了“复用”目的而使用继承,结局并不完美。

#####方式1
子类重写 fly(); 方法, 方法体内什么都不做
缺点:

  1. 代码在多个子类中重复

  2. 改变会牵一发而动全身, 造成其他鸭子类不想要的改变

  3. 运行时的行为不容易改变
    #####利用接口
    把fly() 方法从超类中拿出来, 放入一个Flyable接口中,只有会飞的鸭子才实现该接口;
    同样quack()方法提取到 Quackable 接口中,因为并不是所有的鸭子都会呱呱叫(例如橡皮鸭子)
    缺点:
    代码复用率低

    如果能有一种方法,让我们可以用一种对既有的代码影响最小的方式来修改软件, 那该多好!
    这样我们就可以花较小的时间重做代码,而多让程序去做更酷的事。

软件开发的真理:
不管设计的多好,一段时间之后,总是需要成长和改变,否则软件就会“死亡”

引入设计原则

  • 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
    如果每次新的需求一来, 都会使某些代码发生变化,那么就可以确定,这部门的代码需要被抽出来,和其他稳定的代码有所区分。

  • 针对接口编程,而不是针对实现编程

针对接口编程:意思是“针对超类型(supertype)编程”

处理

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.zyfu.fakecode;

/**
* 超类鸭子
*/
public abstract class Duck {
FlyBehavior flyBehavior;

abstract void display();

public void swim(){

}

public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}

public FlyBehavior getFlyBehavior() {
return flyBehavior;
}
}

/**
* 子类红头鸭子
**/
class RedHeadDuck extends Duck {

public RedHeadDuck() {
this.flyBehavior = new FlyWithWings();
}

@Override
void display() {

}
}

//飞行行为接口
interface FlyBehavior{
void fly();
}

//实现类---翅膀飞行
class FlyWithWings implements FlyBehavior{
@Override
public void fly() {
System.out.println("用翅膀飞行");
}
}
//实现类---什么都不做
class FlyNoWay implements FlyBehavior{
@Override
public void fly() {
//什么也不做
}
}

“有一个”可能比“是一个”更好
上面将两个类结合起来使用, 这就是组合(composition)。 这种做法与“继承”不同的地方在于,行为不是继承来的,而是和适当的行为对象“组合”起来的

  • 多用组合, 少用继承
    使用组合建立系统具有很大的弹性,不仅可将算法封装成类, 更可以 “在运行时动态的改变行为”,只要组合的“行为对象”符合正确的接口标准即可。

以上的思路就是策略模式

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

支付宝打赏 微信打赏

赞赏是不耍流氓的鼓励