策略模式
含义
策略模式定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
一般情况下我们是将一种行为写成一个类方法,比如计算器类中有加、减、乘、除四种方法,而策略模式则是将每一种算法都写成一个类,然后动态地选择使用哪一个算法。
使用案例
-
默认主题与自定义主题功能的实现
-
Shiro提供三种验证策略
优缺点比较
-
优点
讲完上面的例子,优点已经十分明显了,那就是遵循了开闭原则,扩展性良好。 -
缺点
随着你的策略增加,你的类也会越来越多。
所有的策略类都要暴露出去,所以如果你在实际开发中使用了策略模式,一定要记得写好文档让你的伙伴们知道已有哪些策略。就像 Shiro 默认提供了三种验证策略,就必须在文档中写清楚,否则我们根本不知道如何使用。
当然,权衡利弊,跟优点比起来,这些缺点都不算事儿。
示例
示例1:计算器
首先需要一个算法框架的接口,我们顶一个Operation
类作为算法族的集合,其中有一个 示例的操作方法doOperation
。
/**
* 策略模式组件:算法框架,由此将衍生出一个算法族
*/
public interface Operation {
int doOperation(int num1, int num2);
}
定义一个计算器类,作为操作所有功能算法的入口:
/**
* 计算器类,操作Operation算法的提供者
*/
public class Calculator {
private Operation operation;
public void setOperation(Operation operation) {
this.operation = operation;
}
public int doOperation(int num1, int num2) {
return this.operation.doOperation(num1, num2);
}
}
定义一个加法操作OperationAdd
/**
* 加法操作,Operation算法的实现类之一
*/
public class OperationAdd implements Operation {
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
定义一个减法操作OpreationSub
/**
* 减法操作,Opreation算法的实现类之一
*/
public class OpreationSub implements Operation {
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
示例2:主题
首先,定义一个算法框架ThemeInterface
用来表示操作主题相关的方法的签名的集合。
/**
* 定义主题应当具有的功能接口
* 所有的主题都应当实现该接口
*/
public interface ThemeInterface {
void showTheme();
}
接下来,定义一个主题管理器类ThemeManager
,它是用以操作主题相关功能的入口,可以理解为是主题管理器的入口类,里面提供了所有支持的操作主体的方法:
public class ThemeManager {
private ThemeInterface theme;
public void setTheme(ThemeInterface theme) {
this.theme = theme;
}
public void showTheme() {
this.theme.showTheme();
}
}
然后我们可能有一个默认的主题DefaultTheme
:
/**
* 默认主题
*/
public class DefaultTheme implements ThemeInterface {
@Override
public void showTheme() {
//此处设置主题颜色,背景,字体等
System.out.println("显示默认主题");
}
}
我们也可以切换到某个自定义的主题:
public class MyTheme implements ThemeInterface {
@Override
public void showTheme() {
System.out.println("我的自定义主题");
}
}
单元测试
import com.netease.learn.designPattern.strategy.calculator.Calculator;
import com.netease.learn.designPattern.strategy.calculator.OperationAdd;
import com.netease.learn.designPattern.strategy.theme.DefaultTheme;
import com.netease.learn.designPattern.strategy.theme.MyTheme;
import com.netease.learn.designPattern.strategy.theme.ThemeManager;
import org.junit.Test;
public class StrategyTest {
@Test
public void test1() {
Calculator calculator = new Calculator();
calculator.setOperation(new OperationAdd());
int result = calculator.doOperation(1, 2);
System.out.println(result);
}
@Test
public void test2() {
ThemeManager themeManager = new ThemeManager();
themeManager.setTheme(new DefaultTheme());
themeManager.showTheme();
themeManager.setTheme(new MyTheme());
themeManager.showTheme();
}
}
网友评论