zoukankan      html  css  js  c++  java
  • 混合模式(策略模式+工厂方法模式+门面模式)

    使用这三种模式设计一个简单的计算器程序:计算器是用于计算数值之间进行数学计算后所获得的值。它包含基本的"加减"功能。以上对以上需求进行分析可以得出计算有两种策略(+与-)。

    计算策略的实现:

    /*抽象策略*/
    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接口,都不用枚举了,这样更灵活。

  • 相关阅读:
    SpringBoot-Mysql模板多数据源加载
    SpringCloud-动态配置变化监控-获取变化(支持Config、Nacos)
    SpringBoot-ElasticJob封装快速上手使用(分布式定时器)
    关键字(标签)提示组件——拼音、汉字混合搜索
    写一个高性能的敏感词检测组件
    一个文件搞定Asp.net core 3.1动态页面转静态页面
    浅谈C#在网络波动时防重复提交
    对RC4算法进行改写,新的加密算法RCX。
    【ToolGood.Words】之【StringSearch】字符串搜索——基于BFS算法
    万能解决方案之彻底解决macOS cocoapods环境的所有问题
  • 原文地址:https://www.cnblogs.com/justuntil/p/5514076.html
Copyright © 2011-2022 走看看