目录
策略模式的定义
定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式算法的变化,不会影响到使用算法的客户。
优点
-
灵活性:策略模式允许在运行时切换算法,提供了灵活性,使客户端可以根据需求选择不同的策略。
-
可维护性:每个策略都被封装在独立的类中,使得代码更易于维护和扩展。
-
解耦:策略模式将算法的实现与使用算法的客户端解耦,客户端只需要关心选择合适的策略即可。
缺点
-
增加类的数量:引入策略模式会增加类的数量,特别是在有多个策略的情况下。
-
客户端必须了解所有策略:客户端需要知道所有可用的策略,并在运行时选择合适的策略,可能会增加客户端的复杂性。
策略模式结构说明
-
策略接口(Strategy Interface):定义了一组算法的通用接口,通常包含一个执行算法的方法。
-
具体策略类(Concrete Strategy):实现策略接口,提供具体的算法实现。
-
上下文类(Context):维护一个策略对象,并在需要时调用策略对象的方法。上下文类通常允许客户端动态地切换策略。
工作流程
-
客户端创建一个上下文对象,并将一个具体的策略对象传递给上下文。
-
当客户端需要使用算法时,它调用上下文的方法,上下文将请求委派给策略对象执行。
-
不同的策略对象可以实现不同的算法,客户端可以根据需求选择不同的策略对象。
代码示例
策略模式解耦的是策略的定义、创建和使用。简单的例子,吃午饭是吃麻辣烫还是套饭简餐。
1.创建抽象策略接口Lunch.
public interface Lunch { void eat(); }
2.创建具体策略吃麻辣烫或者吃套饭简餐
public class MaLaTang implements Lunch { public void eat(){ System.out.println("吃个麻辣烫吧..."); } }
public class TaoFan implements Lunch { public void eat(){ System.out.println("吃个套饭吧..."); } }
3.创建上下文对象,可以理解为策略的使用者,包含策略的引用。
public class Person { private Lunch lunch; public Person(Lunch lunch) { this.lunch = lunch; } public void dinner(){ System.out.println("中午吃什么呢?"); this.lunch.eat(); } }
4.客户端指定使用哪种策略,或者动态的决定策略(需要通过工厂传入type获取策略)。
public static Lunch getLunch(String type){ if (type == null || type.isEmpty()){ throw new IllegalArgumentException("参数不能为空."); } // 这里使用的是简单工厂,if-else直接用了 if (type.equals("A")) { return new MaLaTang(); } else if (type.equals("B")) { return new TaoFan(); } else { return null; } } }
public class Client { public static void main(String[] args) throws IOException { // 静态指定使用什么策略 Person person = new Person(new MaLaTang()); person.dinner(); // 动态判断使用什么策略 System.out.println("================配置文件读取==============="); Properties props = new Properties(); FileInputStream in = new FileInputStream("D:\\config.properties"); props.load(in); String type = props.getProperty("lunch_type"); Person person1 = new Person(LunchFactory.getLunch(type)); person1.dinner(); } }
config.properties放在D盘下为了方便,就配了个lunch_type
应用场景
-
当需要在运行时选择算法时,可以使用策略模式。例如,根据用户的选择来应用不同的排序算法。
-
当一个类有多个行为变种,且这些变种通过条件语句组织在一起时,可以使用策略模式将每个变种封装为一个独立的策略类。
-
当希望隐藏复杂的算法实现细节,使代码更易于维护和扩展时,策略模式非常有用。
本质
策略模式的本质是定义一系列算法,将每个算法封装到独立的策略类中,使得它们可以相互替换。
设计原则
开闭原则(Open-Closed Principle):策略模式遵循开闭原则,允许在不修改客户端代码的情况下添加新的策略类。
与其他设计模式的关系
策略模式与状态模式有些相似,因为它们都允许对象在不同状态下采取不同的行为。不同之处在于,状态模式是根据对象的内部状态来切换行为,而策略模式是根据客户端的选择来切换行为。
开源框架中的应用
-
Spring框架 - Spring AOP(面向切面编程):
-
Spring AOP是Spring框架的一部分,它采用策略模式来支持不同的切面(Aspect)。
-
Spring AOP允许开发人员定义不同的通知(Advice)策略,如前置通知、后置通知、异常通知等,然后将这些通知与切入点关联起来。
-
-
Slf4j - 日志输出策略:
-
Simple Logging Facade for Java(Slf4j)是一个Java日志门面,它允许开发人员使用不同的底层日志实现(如Log4j、Logback、JUL等)。
-
Slf4j使用策略模式来将日志输出委托给不同的底层日志库,使得应用程序可以在不同的环境中轻松切换日志实现。
-
-
Spring Security框架 - 认证和授权策略:
-
Spring Security是用于身份验证和授权的框架,它使用策略模式来支持不同的认证和授权策略。
-
开发人员可以选择不同的认证和授权策略,例如基于用户名和密码的认证、基于令牌的认证、基于角色的授权等,以满足应用程序的安全需求。
-