策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变的上下文对象。策略模式适用于变化的环境。
本文目录导读:
策略模式是一种行为设计模式,它使你能在运行时改变对象的行为,在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变的上下文对象,策略模式的主要目标是定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换,本篇文章将深入探讨策略模式的基础概念、实现方式、优缺点以及在实际开发中的应用。
策略模式基础
策略模式是一种对象行为型模式,在策略模式中,一个类的行为或其算法可以在运行时更改,这种类型的设计模式属于行为模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变的上下文对象,策略模式让这些策略可以相互替换,使得算法可以独立于使用它的客户端而变化。
1.1 何时使用策略模式
1、当需要在系统中改变行为时,如果这个行为与其它对象关联紧密,那么使用策略模式可以降低系统的耦合度。
2、当需要添加新的行为时,无需修改现有代码,只需增加一个新的策略类即可。
3、当系统中的策略多于一个,且客户端需要根据当前情况选择不同的策略时,使用策略模式可以使系统更灵活。
1.2 策略模式组成
策略模式主要由以下几个角色组成:
- 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现,此角色给出所有的具体策略类所需的接口。
- 具体策略(ConcreteStrategy)类:包装了相关的算法或行为。
- 上下文(Context)类:持有一个抽象策略类的引用,维护一个对具体策略对象的引用,并定义一些算法,这些算法可以调用具体策略对象的行为。
策略模式实现
2.1 简单示例
下面是一个简单的策略模式示例:
// 抽象策略 interface Strategy { void execute(); } // 具体策略A class ConcreteStrategyA implements Strategy { @Override public void execute() { System.out.println("执行策略A"); } } // 具体策略B class ConcreteStrategyB implements Strategy { @Override public void execute() { System.out.println("执行策略B"); } } // 上下文 class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void executeStrategy() { strategy.execute(); } } public class StrategyPatternDemo { public static void main(String[] args) { // 创建具体策略对象 Strategy strategyA = new ConcreteStrategyA(); Strategy strategyB = new ConcreteStrategyB(); // 创建上下文对象,并设置具体策略对象 Context context = new Context(strategyA); // 执行策略 context.executeStrategy(); // 切换策略 context.setStrategy(strategyB); context.executeStrategy(); } }
2.2 复杂示例
下面是一个复杂的策略模式示例,涉及到多个策略和条件判断:
// 抽象策略接口 interface Strategy { boolean supports(String type); void execute(String type); } // 具体策略A class ConcreteStrategyA implements Strategy { @Override public boolean supports(String type) { return "A".equals(type); } @Override public void execute(String type) { System.out.println("执行策略A,类型:" + type); } } // 具体策略B class ConcreteStrategyB implements Strategy { @Override public boolean supports(String type) { return "B".equals(type); } @Override public void execute(String type) { System.out.println("执行策略B,类型:" + type); } } // 上下文 class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void setStrategy(Strategy strategy) { this.strategy = strategy; } public void executeStrategy(String type) { if (strategy.supports(type)) { strategy.execute(type); } else { System.out.println("不支持的类型:" + type); } } } public class StrategyPatternDemo { public static void main(String[] args) { // 创建具体策略对象 Strategy strategyA = new ConcreteStrategyA(); Strategy strategyB = new ConcreteStrategyB(); // 创建上下文对象,并设置具体策略对象 Context context = new Context(strategyA); // 执行策略 context.executeStrategy("A"); context.executeStrategy("B"); context.executeStrategy("C"); // 切换策略 context.setStrategy(strategyB); context.executeStrategy("B"); context.executeStrategy("C"); } }
策略模式优缺点
3.1 优点
1、策略模式提供了管理相关的算法族的办法,策略类的等级结构定义了一个算法或行为族,恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。
2、策略模式提供了一种交换算法的方式,你可以改变对象的行为,而不需要改变它们的类。
3、策略模式提供了一种封装机制,避免客户端直接使用具体的算法类,客户端只需要知道所选的策略类名,而无需知道内部的逻辑。
4、策略模式使得算法可独立于使用它的客户而变化,这是面向对象设计的基本原则之一。
5、策略模式支持开闭原则,你可以在不改变原有代码的情况下添加新的算法。
3.2 缺点
1、使用策略模式可能会导致系统更加复杂,因为每个策略都需要一个单独的类来表示,会增加系统的复杂度和理解难度。
2、由于每个具体策略类都会产生一个新实例,因此消耗更多的系统资源,可以通过使用享元模式来减少对象实例的数量,但会增加系统的复杂度和理解难度。
3、客户端必须理解每一个策略所代表的行为,以便适时选择恰当的策略类,这增加了客户端使用策略模式的难度,可以通过使用简单工厂模式或享元模式来解决这个问题。
策略模式实际应用
策略模式在实际开发中有很多应用场景,以下是一些常见的例子:
1、价格计算:根据不同的折扣策略来计算商品的价格。
2、排序算法:根据不同的排序需求选择不同的排序算法。
3、数据库访问:根据不同的数据库类型选择不同的访问策略。
4、日志记录:根据不同的日志级别选择不同的日志记录策略。
5、UI设计:根据不同的设备类型选择不同的UI布局策略。
6、网络通信:根据不同的网络环境选择不同的通信策略。