面向对象设计模式:行为型模式之策略模式


[Source] PPT of sk of NEU

一、问题引入:学霸、学渣、学弱

在这里插入图片描述
  上图学霸、学渣、学弱都继承了大学生类,但是我们可以发现:如果一个学渣想变成一个学霸,那么该学渣必须消灭(C++析构),并重新实例化一个学霸。针对上图的设计,学渣想变成学霸?不可能,我们能做的只有消灭学渣。那么学渣如何变成学霸,显然上述设计存在问题,对现实的抽象也不太好。改进如下:
在这里插入图片描述
  em…这个还行,学霸拥有学霸行为、学渣拥有学渣行为、学弱拥有学弱行为,一个学渣想要变成学霸也是可能的了,学渣只要改变学渣行为为学霸行为,那就变成了学霸。

二、策略模式

  • Strategy Pattern,Also Known As:Policy
  • Intent
    • 针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。(客户决定使用哪种算法)
  • 设计原则
    • Separating what changes from what stays the same(把变化从不变中分离出来),即把可能变化的代码独立出来,不要和不变化的代码混在一起;
    • Program to an interface, not an implementation(针对接口而不是针对实现编程)-DIP;
    • Favor composition over inheritance(多用组合,少用继承);
  • 适用情况
    • Many related classes differ only in their behavior(许多相关类的区别仅在于它们的行为)
      • 策略提供了一种配置具有多种行为之一的类的方法(动态地让一个对象在许多行为中选择一种行为)。
    • 系统需要算法的不同变体:当这些变体作为算法的类层次结构实现时,可以使用策略。
    • An algorithm uses data that clients shouldn’t know about (一个算法使用客户端不应该知道的数据). Use the Strategy pattern to avoid exposing complex, algorithm-specific data structures(使用策略模式以避免暴露复杂的、特定于算法的数据结构).
    • 一个类定义了许多行为,这些行为在其操作中显示为多个条件语句:与使用条件语句相反,可以将相关的条件分支移动到它们自己的策略类中。
  • 类图
    在这里插入图片描述
  • Context 与 Strategy 的合作
    • Context 与 Strategy 交互实现算法选择
      • A context may pass all data required by the algorithm to the strategy when the algorithm is called(当算法被调用时,一个 context 可能会传递该算法需要的所有数据到 strategy ).
        • 使得 Context 与 Strategy 解耦。
      • Alternatively, the context can pass itself as an argument to strategy operations(或者,context 可以把自己作为一个参数传递给 strategy 的操作).
        • Context 必须定义更为具体的接口来访问其数据,使得 Context 与 Strategy 耦合。
    • context 传递来自其客户端的请求到其 strategy
      • 通常有一系列的具体的 strategy 供客户端选择。
      • 客户端通常创建并传递一个具体的 strategy 对象到context。
  • 优点
    • 策略类的层次结构定义了一系列算法或行为使得 contexts 能够重用;
    • 避免使用多重条件判断,扩展性良好
    • 子类化的一种替换选择,合成复用原则 CRP
      • 封装算法到独立的策略类集使我们能够独立于 context 而改变算法,使得容易切换、理解与扩展;
    • 消除条件语句
      • 策略模式提供了一个条件语句的替换用于选择期望行为;
    • 策略为相同行为提供了不同实现,客户端可以根据时间-空间权衡来选择策略
  • 缺点
    • 策略类会增多,且所有策略类都需要对外暴露
    • Client must understand how Strategies differ before it can select the appropriate one (在选择恰当策略前客户必须理解不同策略之间的区别 => 增加了客户的使用难度).
    • Strategy 与 Context 的通信开销:不论具体策略是简单或者复杂,策略接口是它们所共享的,因此可能存在一些具体策略不会使用 context 传递过来的所有信息
    • 其它

三、应用实例:排序系统

在这里插入图片描述

  • SortAndPrint 类聚合(has-a)了 Sorter 接口
public class SortAndPrint {
    Comparable[] data;
    Sorter sorter;
    public SortAndPrint(Comparable[] data, Sorter sorter) {
        this.data = data;
        this.sorter = sorter;
    }
    public void execute() {
        print();
        sorter.sort(data);
        print();
    }
    public void print() {
        for (int i = 0; i < data.length; i++) {
            System.out.print(data[i] + ", ");
        }
        System.out.println("");
    }
}

特别注意 execute() 方法。

  • Sorter 接口
import java.lang.Comparable;

public interface Sorter {
    void sort(Comparable[] data);
}
  • 选择排序
public class SelectionSorter implements Sorter {
    public void sort(Comparable[] data) {
        for (int i = 0; i < data.length - 1; i++) {
            int min = i;
            for (int j = i + 1; j < data.length; j++) {
                if (data[min].compareTo(data[j]) > 0) {
                    min = j;
                }
            }
            Comparable passingplace = data[min];
            data[min] = data[i];
            data[i] = passingplace;
        }
    }
}

三、应用实例:JDK java.util.concurrent.ThreadPoolExecutor

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
excute()
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值