Fork me on GitHub

设计模式———策略模式

策略模式:分别封装行为接口,实现算法族,超类里面放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能,此模式让行为算法的变化独立于算法的使用者。

注意点

1.分析项目中变化部分与不变部分

2.多用组合少用继承;用行为类组合,而不是行为的继承。更有弹性

3.设计模式有没有相应的库直接使用?有些库或框架本身就用某种设计模式设计的

策略模式设计到三个角色:

环境角色(Context):持有一个Strategy的引用

抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现,此角色给出所有的具体策略类所需的接口

具体策略(ConcreteStrategy)角色:包装了相关的算法或行为

案例

模拟飞行的鸭子,设计鸭子超类(Quack、Swim、display),扩展超类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//鸭子超类
public abstract class Duck {
public Duck()
{

}
public void Quack()
{
System.out.println("~~gaga~~");
}
public abstract void display();
public void swim()
{
System.out.println("~~im swim~~");
}
}
1
2
3
4
5
6
7
8
//绿头鸭
public class GreenHeadDuck extends Duck {

@Override
public void display() {
System.out.println("**GreenHead");
}
}
1
2
3
4
5
6
7
8
//红头鸭
public class RedHeadDuck extends Duck {

@Override
public void display() {
System.out.println("**RedHead");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
//测试类
public static void main(String[] args) {
GreenHeadDuck gDuck = new GreenHeadDuck();
RedHeadDuck rDuck = new RedHeadDuck();
gDuck.display();
gDuck.Quack();
gDuck.swim();

rDuck.display();
rDuck.Quack();
rDuck.swim();
}

新需求:如果要添加一个飞行功能,一种方法是在超类里添加Fly方法,但是绿头鸭和红头鸭都会实现这个方法,但是并不是所有的鸭子不会飞,这中方法让所有子类都会飞了,这是不科学的。

继承的问题:对类的局部改动,尤其是超类的局部改动,会影响其他部分,影响会有溢出效应。

如果继续用OO原理,子类覆盖超类里Fly的方法,使某个子类实现不会飞行的功能,但是如果有许多子类,那么这也是不可行的。

1
2
3
4
public void Fly()
{
System.out.println("~~fly~~")
}

使用策略模式:

抽象策略角色(接口):

​ public interface FlyBehavior( void fly(); )

​ public interface QuackBehavior( void quack(); )

环境角色:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public abstract class Duck {

FlyBehavior flyBehavior;
QuackBehavior quackBehavior;

public Duck()
{

}
public void Fly()
{
flyBehavior.fly();
}
public void Quack()
{
quackBehavior.quack();
}
public abstract void display();
}

具体策略角色:在构造方法里就把两个行为定义上,好的飞行,嘎嘎叫,具体的行为不是在类里实现了,而是直接new一个行为族对象。用行为族的对象来展现行为,不是把具体行为写在类的对象里。

1
2
3
4
5
6
7
8
9
10
11
12
public class GreenHeadDuck extends Duck {
public GreenHeadDuck()
{
flyBehavior = new GoodFlyBehavior();
quackBehavior = new GaGaQuackBehavior();

}
@Override
public void display() {
System.out.println("**GreenHead");
}
}
1
2
3
4
5
6
7
public class GoodFlyBehavior implements FlyBehavior {

@Override
public void fly() {

}
}
1
2
3
4
5
6
7
public class GaGaQuackBehavior implements QuackBehavior {

@Override
public void quack() {

}
}