「尺有所短,寸有所长;不忘初心,方得始终。」
一、策略模式是什么
策略模式「定义了一系列算法,并将每个算法封装起来,使他们可以在运行时相互替换,且算法的变化不会影响到使用算法的客户」。属于行为型模式。
「主要作用」:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
「主要解决」:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
「何时使用」:一个系统有许多许多类,而区分它们的只是他们直接的行为。
「如何解决」:将这些算法封装成一个一个的类,任意地替换。
「关键代码」:实现同一个接口。
![设计模式(14):策略模式 设计模式(14):策略模式](https://www.bmabk.com/wp-content/uploads/2022/05/post-loading.gif)
需要设计一个接口,为一系列实现类提供统一的方法,多个实现类实现该接口,设计一个抽象类(可有可无,属于辅助类),提供辅助函数。
策略模式定义和封装了一系列的算法,它们是可以相互替换的,也就是说它们具有共性,而它们的共性就体现在策略接口的行为上,另外为了达到最后一句话的目的,也就是说让算法独立于使用它的客户而独立变化,我们需要让客户端依赖于策略接口。
一种很简单的解释,「在我们的开发过程中,经常会遇到大量的if…else或者switch…case语句,当这些语句在开发中只是为了起到分流作用,这些分流和业务逻辑无关,那么这个时候就可以考虑用策略模式」
二、策略模式的适用场景
-
当想使用对象中各种不同的算法变体,并希望能在运行时切换算法时, 可使用策略模式。 -
当有许多仅在执行某些行为时略有不同的相似类时, 可使用策略模式。 -
如果算法在上下文的逻辑中不是特别重要,使用策略模式能将类的业务逻辑与其算法实现细节隔离开来。 -
当类中使用了复杂条件运算符以在同一算法的不同变体中切换时, 可使用策略模式。
「在开发过程中,经常会遇到大量的if…else或者switch…case语句,当这些语句在开发中只是为了起到分流作用,这些分流和业务逻辑无关,那么这个时候就可以考虑用策略模式」
三、策略模式结构
-
「上下文(Context)角色」:持有一个维护指向具体策略的引用, 且仅通过策略接口与该对象进行交流。
-
「抽象策略(Strategy)角色」:通常由一个接口或抽象类实现。声明了一个上下文用于执行策略的方法。
-
「具体策略(ConcreteStrategy)角色」:实现了上下文所用算法的各种不同变体。
-
「客户端」 :创建一个特定策略对象并将其传递给上下文。上下文则会提供一个设置器以便客户端在运行时替换相关联的策略。
![设计模式(14):策略模式 设计模式(14):策略模式](https://www.bmabk.com/wp-content/uploads/2022/05/post-loading.gif)
四、策略模式实现方式
-
创建一个策略接口,声明算法所有变体的通用接口方法。 -
创建各个算法类并且实现策略接口。 -
在上下文中添加一个成员变量用于保存对于策略对象的引用。然后提供设置器以修改该成员变量。上下文仅可通过策略接口同策略对象进行交互。 -
客户端必须将上下文类与相应策略进行关联, 使上下文可以预期的方式完成其主要工作。
五、策略模式的实现
-
「抽象策略角色实现」
/**
* 抽象策略角色: 定义所有支持的算法的公共接口
*/
public interface Strategy {
public String methodA();
public String methodB();
} -
「具体策略角色实现」
/**
* 具体策略 :A 策略
*/
public class AStrategy implements Strategy {
@Override
public String methodA() {
return "策略A 的methodA";
}
@Override
public String methodB() {
return "策略A 的methodB";
}
}
/**
* 具体策略 :B 策略
*/
public class BStrategy implements Strategy {
@Override
public String methodA() {
return "策略B 的methodA";
}
@Override
public String methodB() {
return "策略B 的methodB";
}
} -
「上下文角色实现」
/**
* 上下文角色 :维护指向具体策略的引用
*/
public class Context {
private Strategy Strategy;
public Context(Strategy Strategy) {
this.Strategy = Strategy;
}
public String methodA() {
return Strategy.methodA();
}
public String methodB() {
return Strategy.methodB();
}
} -
「客户端代码实现」
public static void main(String[] args) {
Context context = new Context(new BStrategy());
System.out.println(context.methodA());
System.out.println(context.methodB());
}
六、策略模式和简单工厂模式的结合
-
「上下文角色实现」
/**
* 上下文角色
*/
public class Context {
private Strategy strategy;
public Context(String type) {
switch (type){
case "A":
this.strategy = new AStrategy();
break;
case "B":
this.strategy = new AStrategy();
break;
}
}
public String methodA() {
return strategy.methodA();
}
public String methodB() {
return strategy.methodB();
}
} -
「客户端代码实现」
public static void main(String[] args) {
Context context = new Context("A");
System.out.println(context.methodA());
System.out.println(context.methodB());
}
「策略模式和简单工厂模式的结合后,客户端只需要知道Context一个类,降低了耦合性。」
六、策略模式的优缺点
「优点:」
-
结构清晰,把策略分离成一个个单独的类,使得程序更清晰。 -
代码耦合度降低,安全性提高。
「缺点:」
-
客户端必须要知道所有的策略类,才能确定使用那个策略,所以策略模式适用于提前知道所有策略的情况下。 -
策略类数量增多,增加算法,需要新增策略类。
七、策略模式和简单工厂模式的区别
-
策略模式和简单工厂模式都是通过多态来实现不同子类的选取。 -
在简单工厂模式中实现了通过条件选取一个类去实例化对象,策略模式则将选取相应对象的工作交给模式的使用者,它本身不去做选取工作。 -
简单工厂模式中只需要传递相应的条件就能得到想要的一个对象,然后通过这个对象实现算法的操作 -
策略模式使用时必须首先创建策略对象作为参数传递进去,通过该对象调用不同的算法。
八、总结
策略模式,「实质是对算法的封装 , 它把算法的责任和算法本身分割开 , 委派给不同的对象管理」,用户可以自由选择这些算法进行操作。策略模式本身理解起来没什么难点,但是在实际应用中其本身主要结合工厂模式一起使用。
原文始发于微信公众号(星河之码):设计模式(14):策略模式
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/27136.html