使用这三种模式设计一个简单的计算器程序:计算器是用于计算数值之间进行数学计算后所获得的值。它包含基本的"加减"功能。以上对以上需求进行分析可以得出计算有两种策略(+与-)。
计算策略的实现:
/*抽象策略*/
public interface Strategy
{
/*定义了计算策略所拥有的算法*/
public int calculate(int a,int b);
}
/*加法策略的实现*/
public class AddStrategy implements Strategy
{
@Override
public int calculate(int a, int b)
{
return a+b;
}
}
/*减法策略的实现*/
public class SubStrategy implements Strategy
{
@Override
public int calculate(int a, int b)
{
return a-b;
}
}
此时还需要一个封装策略的对象,让策略可以互换:
public class StrategyContext
{
/*封装了策略对象*/
private Strategy strategy = null;
public StrategyContext(Strategy strategy)
{
this.strategy = strategy;
}
/*实现了策略可以互换的功能*/
public void setStrategy(Strategy strategy)
{
this.strategy = strategy;
}
public int execute(int a,int b)
{
return this.strategy.calculate(a, b);
}
}
为了避免策略模式必须要将具体的策略暴露给高层模块的缺点,我们使用工厂来生成策略,现在高层模块只需要一个约束条件就可以获得需要的策略。
策略生成工厂的实现:
/*策略生成抽象工厂*/
public interface Factory
{
/*定义一个生成策略的接口,其参数还可以使用一个配置文件来实现约束条件,这里使用了枚举*/
public Strategy createStrategy(StrategyEnum strategyEnum);
}
public class StrategyFactory implements Factory
{
@Override
public Strategy createStrategy(StrategyEnum strategyEnum)
{
Strategy strategy = null;
try
{
String strategyName = strategyEnum.getStrategyName();
Class<?> clazz = Class.forName(strategyName);
strategy = (Strategy)clazz.newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
return strategy;
}
}
每次进行计算的步骤为:获取工厂、获取策略、封装策略、计算结果。这样写比较麻烦,高层模块为了计算一个结果还需要记住执行顺序,这时候我们可以使用门面模式来屏蔽子系统的复杂性,为高层模块提供一个计算接口即可。
计算机器门面的实现:
public class FacadeContext
{
/*门面模式不参与子系统的逻辑,所以对子系统进行了一次封装*/
private Factory factory = new StrategyFactory();
private StrategyContext context = new StrategyContext(null);
public FacadeContext(){}
public int calculate(int a,int b,StrategyEnum strategy)
{
this.context.setStrategy(this.factory.createStrategy(strategy));
return this.context.execute(a, b);
}
}
/*计算器的门面,简单的委托类,为高层提供一个反问子系统的接口,让高层模块不再依赖子系统*/
public class CalculatorFacade
{
private FacadeContext context = new FacadeContext();
public CalculatorFacade()
{}
public int calculate(int a,int b,StrategyEnum strategy)
{
return this.context.calculate(a, b, strategy);
}
}
来看看场景类:
public class Client
{
public static void main(String[] args)
{
/*获取门面,使用其提供的接口访问子系统*/
CalculatorFacade calculatorFacade = new CalculatorFacade();
System.out.println("2+2="+calculatorFacade.calculate(2, 2, StrategyEnum.ADD));
}
}
附:StrategyEnum枚举代码:
public enum StrategyEnum
{
ADD("com.suxiaolei.calculator.strategy.AddStrategy"),
SUB("com.suxiaolei.calculator.strategy.SubStrategy");
private String strategyName;
private StrategyEnum(String strategyName)
{
this.strategyName = strategyName;
}
public String getStrategyName()
{
return this.strategyName;
}
}
以上是混合使用三种模式的一个简单例子,可以看出灵活搭配模式能让系统更健壮,灵活性更高,扩展性更强。在上述例子添加策略非常非常的容易,只需要继承Strategy接口即可,然后在枚举中增加对应的策略类名即可,高层代码一点也不用改变。其实要是使用配置文件的方式,则只需要继承Strategy接口,都不用枚举了,这样更灵活。