【设计模式】策略模式(Strategy Pattern)

在这里插入图片描述

 

🔥 核心

策略模式就是定义一系列的算法,把它们一个个封装到不同的类中,并且使它们可相互替换。

 

🙁 问题场景

你是一名选择恐惧症重度患者。

你快要迟到了,但当你刚踏出家门后,就犯了难——你可以选择骑自行车,也可以做公交车,还可以预约出租车,甚至干脆跑去学校。

 

🙂 解决方案

每一种交通方式,就是一种策略。

如果让你写代码,对于这么多种交通方式,你打算用使用 if-else ,将这么多选择和逻辑挤在一个类当中吗?

我们有更加优美的设计——对于每一种交通方式,即每一种策略,将它封装到一个独立的类;再设置一个上下文对象,它可以执行某一种策略,但不知道是哪种具体的策略;你想运行哪种具体的策略,就将这个策略的对象传递给上下文对象就行。

嗯嗯,是不是非常非常非常非常非常非常简单?

 

🌈 有趣的例子

有一个奇怪的 计算器(Calculator) ,它只能进行一种运算。

至于究竟执行的是哪种运算,需要我们给它传入一个运算策略对象。

在这里插入图片描述

 策略(接口)
interface Strategy {
    int doOperation(int num1, int num2);
}

 加法策略
class OperationAdd implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}

 减法策略
class OperationSub implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}

 乘法策略
class OperationMul implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 * num2;
    }
}

 除法策略
class OperationDiv implements Strategy {
    @Override
    public int doOperation(int num1, int num2) {
        return num1 / num2;
    }
}


 计算器
class Calculator {
    // 拥有一个策略对象成员变量
    private Strategy strategy;

    // 设置策略
    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    // 执行策略
    public int executeStrategy(int num1, int num2) {
        return strategy.doOperation(num1, num2);
    }
}
public class StrategyPatternDemo {
    public static void main(String[] args) {

        // 获取计算器
        Calculator calculator = new Calculator();

        // 设置加法策略并执行
        calculator.setStrategy(new OperationAdd());
        System.out.println(calculator.executeStrategy(12, 4));

        // 设置减法策略并执行
        calculator.setStrategy(new OperationSub());
        System.out.println(calculator.executeStrategy(12, 4));

        // 设置乘法策略并执行
        calculator.setStrategy(new OperationMul());
        System.out.println(calculator.executeStrategy(12, 4));

        // 设置除法策略并执行
        calculator.setStrategy(new OperationDiv());
        System.out.println(calculator.executeStrategy(12, 4));
    }
}
16
8
48
3

 

☘️ 使用场景

◾️当你想使用对象中各种不同的算法变体,并希望能在运行时切换算法时,可使用策略模式。

策略模式让你能够将对象关联至可以不同方式执行特定子任务的不同子对象,从而以间接方式在运行时更改对象行为。

◾️当你有许多仅在执行某些行为时略有不同的相似类时,可使用策略模式。

策略模式让你能将不同行为抽取到一个独立类层次结构中,并将原始类组合成同一个,从而减少重复代码。

◾️如果算法在上下文的逻辑中不是特别重要,使用该模式能将类的业务逻辑与其算法实现细节隔离开来。

策略模式让你能将各种算法的代码、内部数据和依赖关系与其他代码隔离开来。不同客户端可通过一个简单接口执行算法,并能在运行时进行切换。

◾️当类中使用了复杂条件运算符以在同一算法的不同变体中切换时,可使用该模式。

策略模式将所有继承自同样接口的算法抽取到独立类中,因此不再需要条件语句。原始对象并不实现所有算法的变体,而是将执行工作委派给其中的一个独立算法对象。

 

🧊 实现方式

(1)从上下文类中找出修改频率较高的算法(也可能是用于在运行时选择某个算法变体的复杂条件运算符)。

(2)声明该算法所有变体的通用策略接口。

(3)将算法逐一抽取到各自的类中,它们都必须实现策略接口。

(4)在上下文类中添加一个成员变量用于保存对于策略对象的引用。然后提供设置器以修改该成员变量。上下文仅可通过策略接口同策略对象进行交互,如有需要还可定义一个接口来让策略访问其数据。

(5)客户端必须将上下文类与相应策略进行关联,使上下文可以预期的方式完成其主要工作。

 

🎲 优缺点

  ➕ 你可以在运行时切换对象内的算法。

  ➕ 你可以使用组合来代替继承。

  ➕ 你可以将算法的实现和使用算法的代码隔离开来。

  ➕ 开闭原则。你无需对上下文进行修改就能够引入新的策略。

  ➖ 策略类的数量有膨胀的风险。

  ➖ 客户端必须知晓策略间的不同——它需要选择合适的策略。

  ➖ 如果你的算法极少发生改变,那么没有任何理由引入新的类和接口。使用该模式只会让程序过于复杂。

 

🌸 补充

 现如今,许多编程语言已经支持函数类型的参数(JavaScript),有的则曲线救国使用匿名函数(Java)。

 这都比我们手动的实现策略模式要简洁,

 

🔗 参考网站

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值