盒子
盒子
文章目录
  1. 策略模式:
    1. 类图
  2. 优点
  3. 缺点
  4. 例子

设计模式之策略模式

策略模式:

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

类图

策略类图

抽象策略角色strategy: 策略类,通常由一个接口或者抽象类实现。
具体策略角色ConcreteStrategyA,ConcreteStrategyB,ConcreteStrategyC:包装了相关的算法和行为。
环境角色Context:持有一个策略类的引用,最终给客户端调用。


优点

  • 策略模式提供了管理算法族的办法
  • 策略模式提供了可以替换继承关系的方法
  • 使用策略模式可以避免使用多重条件转移语句

缺点

  • 客户端必须知道所有的策略,并自行决定使用哪一个策略类
  • 策略模式造成很多的策略类,每个具体策略类都会产生一个新类。

例子

我们有一套关于鸭子的程序,Duck是超类,实现了鸭子共有的行为如 quack(“呱呱叫”) swim(“游泳”),子类为具体的鸭子分别实现了display()//外表;
RedHeadDuck:红头鸭
MallardDuck:绿头鸭
策略1

然后我们需要给鸭子增加飞行的动作,我们在超类中增加了fly()方法
策略2

新需求来了,我们需要增加两个子类,分别是
RubberDuck:橡皮鸭 需要重写 quack(),display(),fly()这三个方法
DecoyDuck:诱饵鸭 也需要重写 quack(),display(),fly()这三个方法
如果再继续使用继承,会发现一些问题

  • 代码在多个子类中重复实现
  • 运行时的行为不容易改变
  • 很难知道所有鸭子的全部行为
  • 鸭子不能同时又飞又叫
  • 改变会牵一发而动全身,造成其他鸭子不想要的改变

为了避免这些问题,我们把共有的行为抽象成接口,通过子类实现接口的方式来增加行为。
策略3

显然不是个好方法


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


我们使用策略模式来设计
首先我们要分开“变化和不变化的部分”,我们知道Duck中的fly()和quack()会随着鸭子的不同而变化,我们将它们从Duck中取出来,建立一组新类来代表每个行为
策略4
这样的设计,可以让飞行和呱呱叫的动作被其他对象复用,因为这些行为已经与鸭子类无关了。
而且我们可以新增一些行为,不会影响到既有的行为类,也不会影响使用到飞行行为的鸭子类

下面整合鸭子的行为。在Duck中增加两个变量,分别为flyBechavior和quackBechavior。在Duck中实现fly和quack

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class Duck {
QuackBechavior quackBechavior;
FlyBechavior flyBechavior;

public abstract void display();

public void performquack(){
quackBechavior.quack();
};
public void performfly(){
flyBechavior.fly();
};

void swim(){
System.out.println("swim");
};

}

具体鸭子类MallardDuck
1
2
3
4
5
6
7
8
9
10
11
public class MallardDuck extends Duck {

public MallardDuck(){
quackBechavior = new Quack();
flyBechavior = new FlyWithWings();
}

void display() {
System.out.println("MallardDuck");
}
}

策略5