flea-common使用之通用策略模式实现

简介: 跟着 Huazie 一起了解通用策略模式实现【Flea Strategy】

flea-logo.png

1. 概述

策略模式(Strategy Pattern)作为一种软件设计模式,用来实现对象的某个行为,该行为在不同的场景中拥有不同的实现逻辑。它定义了一组算法,同时将这些算法封装起来,并使它们之间可以互换。

常用的策略模式有如下三个角色:

  • 抽象策略角色 --- Strategy
    抽象策略类,通常为一个接口,其中定义了某个策略行为【即策略算法标识】。

  • 具体策略角色 --- ConcreteStrategy
    具体策略类,实现抽象策略中的策略行为;每一个具体策略类即代表一种策略算法。

  • 上下文角色 --- Context
    上下文类,起承上启下封装作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。

本篇在上述常用的策略模式基础上,结合门面模式和调整后的策略上下文,构建了一套通用策略模式实现。

下面我们用这套通用策略模式来模拟一下各种动物的喊叫行为:

image.png

2. 参考

flea-common使用之通用策略模式实现 源代码

3. 实现

3.1 定义Flea策略接口类

IFleaStrategy 定义了通用的策略行为,T 类型表示 Flea 策略执行结果对应的类型,P 类型表示 Flea 策略上下文参数。 具体代码如下:

/**
 * Flea策略接口,定义统一的策略执行方法。
 *
 * @param <T> Flea策略执行结果对应的类型
 * @param <P> Flea策略上下文参数
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public interface IFleaStrategy<T, P> {
   

    /**
     * 策略执行
     *
     * @param contextParam Flea策略上下文参数
     * @return 策略执行结果对应的类型
     * @throws FleaStrategyException Flea策略异常
     * @since 1.1.0
     */
    T execute(final P contextParam) throws FleaStrategyException;
}

3.2 定义狗喊叫声策略类

DogVoiceStrategy 用于定义狗喊叫声策略,返回 "阿狗【" + name + "】正在喊叫着;汪汪汪"

/**
 * 狗喊叫声策略
 *
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class DogVoiceStrategy implements IFleaStrategy<String, String> {
   

    @Override
    public String execute(String name) throws FleaStrategyException {
   
        return "阿狗【" + name + "】正在喊叫着;汪汪汪";
    }

}

3.3 定义猫喊叫声策略类

CatVoiceStrategy 用于定义猫喊叫声策略,返回 "阿猫【" + name + "】正在喊叫着;喵喵喵"

/**
 * 猫喊叫声策略
 *
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class CatVoiceStrategy implements IFleaStrategy<String, String> {
   

    @Override
    public String execute(String name) throws FleaStrategyException {
   
        return "阿猫【" + name + "】正在喊叫着;喵喵喵";
    }

}

3.4 定义鸭喊叫声策略类

DuckVoiceStrategy 定义鸭喊叫声策略,返回 "阿鸭【" + name + "】正在喊叫着;嘎嘎嘎"

/**
 * 鸭喊叫声策略
 *
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class DuckVoiceStrategy implements IFleaStrategy<String, String> {
   

    @Override
    public String execute(String name) throws FleaStrategyException {
   
        return "阿鸭【" + name + "】正在喊叫着;嘎嘎嘎";
    }

}

3.5 定义策略上下文接口类

IFleaStrategyContext 策略上下文接口,定义统一的策略上下文调用方法,同时可通过 getContext 获取上下文参数,setContext 设置上下文参数。

/**
 * Flea策略上下文接口,定义统一的策略上下文调用方法。
 *
 * @param <T> Flea策略执行结果对应的类型
 * @param <P> Flea策略上下文参数
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public interface IFleaStrategyContext<T, P> {
   

    /**
     * 策略上下文调用
     *
     * @param strategy 策略名称
     * @return 策略执行结果对应的类型
     * @throws FleaStrategyException Flea策略异常
     * @since 1.1.0
     */
    T invoke(String strategy) throws FleaStrategyException;

    /**
     * 设置策略上下文参数
     *
     * @param contextParam 上下文参数对象
     * @since 1.1.0
     */
    void setContext(P contextParam);

    /**
     * 获取策略上下文参数
     *
     * @return 策略上下文参数
     * @since 1.1.0
     */
    P getContext();
}

3.6 定义Flea抽象策略上下文类

FleaStrategyContext Flea 抽象策略上下文类,封装了策略执行的逻辑,对外屏蔽高层模块对策略的直接访问。抽象方法 init 用于初始化 Flea 策略实现 Map,该方法由Flea 策略抽象上下文的子类实现,并在策略上下文子类实例化时,调用该方法完成具体初始化的工作。

/**
 * Flea抽象策略上下文,封装了公共的策略执行逻辑,
 * 其中Flea策略Map由其子类进行初始化,键为策略名,
 * 值为具体的Flea策略实例。
 *
 * @param <T> Flea策略执行结果对应的类型
 * @param <P> Flea策略上下文参数
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public abstract class FleaStrategyContext<T, P> implements IFleaStrategyContext<T, P> {
   

    private Map<String, IFleaStrategy<T, P>> fleaStrategyMap; // Flea策略Map

    private P contextParam; // Flea策略上下文参数

    /**
     * 初始化策略上下文
     *
     * @since 1.1.0
     */
    public FleaStrategyContext() {
   
        fleaStrategyMap = init();
    }

    /**
     * 初始化策略上下文
     *
     * @param contextParam Flea策略上下文参数
     * @since 1.1.0
     */
    public FleaStrategyContext(P contextParam) {
   
        this();
        this.contextParam = contextParam;
    }

    /**
     * 初始化Flea策略Map
     *
     * @return Flea策略Map
     * @since 1.1.0
     */
    protected abstract Map<String, IFleaStrategy<T, P>> init();

    @Override
    public T invoke(String strategy) throws FleaStrategyException {
   
        if (ObjectUtils.isEmpty(fleaStrategyMap)) {
   
            throw new FleaStrategyException("The Strategy Map is not initialized!");
        }
        IFleaStrategy<T, P> fleaStrategy = fleaStrategyMap.get(strategy);
        if (ObjectUtils.isEmpty(fleaStrategy)) {
   
            throw new FleaStrategyNotFoundException("The Strategy [name =\"" + strategy + "\"] is not found!");
        }
        return fleaStrategy.execute(contextParam);
    }

    @Override
    public void setContext(P contextParam) {
   
        this.contextParam = contextParam;
    }

    @Override
    public P getContext() {
   
        return contextParam;
    }
}

3.7 定义动物喊叫声策略上下文类

AnimalVoiceContext 动物喊叫声策略上下文,继承 Flea 抽象策略上下文,实现 init 方法,用于初始化 Flea 策略实现 Map,其中 key 为 策略名,value 为 具体的动物喊叫声策略实现类;Collections.unmodifiableMap 用于返回一个 只读Map

/**
 * 动物喊叫声策略上下文
 *
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class AnimalVoiceContext extends FleaStrategyContext<String, String> {
   

    private static Map<String, IFleaStrategy<String, String>> fleaStrategyMap;

    static {
   
        fleaStrategyMap = new HashMap<>();
        fleaStrategyMap.put("dog", new DogVoiceStrategy());
        fleaStrategyMap.put("cat", new CatVoiceStrategy());
        fleaStrategyMap.put("duck", new DuckVoiceStrategy());
        fleaStrategyMap = Collections.unmodifiableMap(fleaStrategyMap);
    }

    public AnimalVoiceContext() {
   
    }

    public AnimalVoiceContext(String contextParam) {
   
        super(contextParam);
    }

    @Override
    protected Map<String, IFleaStrategy<String, String>> init() {
   
        return fleaStrategyMap;
    }
}

3.8 定义Flea策略门面

FleaStrategyFacade 定义 Flea 策略调用的统一入口

/**
 * Flea策略门面,定义策略调用的统一入口。
 *
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class FleaStrategyFacade {
   

    private FleaStrategyFacade() {
   
    }

    /**
     * 策略门面调用方法
     *
     * @param strategy            策略名
     * @param fleaStrategyContext 策略上下文
     * @param <T>                 Flea策略执行结果对应的类型
     * @param <P>                 Flea策略上下文参数
     * @return Flea策略执行结果对应的类型
     * @throws FleaStrategyException Flea策略异常
     * @since 1.1.0
     */
    public static <T, P> T invoke(String strategy, IFleaStrategyContext<T, P> fleaStrategyContext) throws FleaStrategyException {
   
        return fleaStrategyContext.invoke(strategy);
    }
}

4. 测试

单元自测类可查看 FleaStrategyTest

/**
 * @author huazie
 * @version 1.1.0
 * @since 1.1.0
 */
public class FleaStrategyTest {
   

    private static final FleaLogger LOGGER = FleaLoggerProxy.getProxyInstance(FleaStrategyTest.class);

    @Test
    public void testStrategy() {
   

        AnimalVoiceContext context = new AnimalVoiceContext("旺财");
        LOGGER.debug(FleaStrategyFacade.invoke("dog", context));

        context.setContext("Tom");
        LOGGER.debug(FleaStrategyFacade.invoke("cat", context));

        AnimalVoiceContext context1 = new AnimalVoiceContext();
        context1.setContext("Donald");
        LOGGER.debug(FleaStrategyFacade.invoke("duck", context1));

    }
}

单元测试类运行结果如下:

image.png

总结

好了,通用策略模式模式实现--Flea Strategy 已讲解完毕,欢迎大家使用 !

目录
相关文章
|
7月前
|
设计模式 安全 NoSQL
【设计模式】JAVA Design Patterns——Abstract-document(抽象文档模式)
【设计模式】JAVA Design Patterns——Abstract-document(抽象文档模式)
|
7月前
|
设计模式 算法 Java
【设计模式】JAVA Design Patterns——Builder(构造器模式)
【设计模式】JAVA Design Patterns——Builder(构造器模式)
|
7月前
|
设计模式 Java 数据库
【设计模式】JAVA Design Patterns——Converter(转换器模式)
转换器模式旨在实现不同类型间的双向转换,减少样板代码。它通过通用的Converter类和特定的转换器(如UserConverter)简化实例映射。Converter类包含两个Function对象,用于不同类型的转换,同时提供列表转换方法。当需要在逻辑上对应的类型间转换,或处理DTO、DO时,此模式尤为适用。
【设计模式】JAVA Design Patterns——Converter(转换器模式)
|
7月前
|
XML JSON 网络架构
flea-jersey使用之Flea RESTful接口介绍
本篇介绍 Flea框架下 flea-jersey 模块下的 Flea RESTful接口
60 1
flea-jersey使用之Flea RESTful接口介绍
|
7月前
|
数据安全/隐私保护 开发框架
flea-auth使用之功能子模块介绍
本篇介绍笔者 Flea框架下的 flea-auth模块中的 功能子模块
69 1
flea-auth使用之功能子模块介绍
|
7月前
|
Java
flea-common使用之本地国际化实现
本篇 Huazie 介绍 Flea框架下的本地国际化实现 — Flea I18N
65 2
flea-common使用之本地国际化实现
.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法
.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法
173 0
【C++】类的构造函数的基本介绍(A basic introduction to constructors of classes)
【C++】类的构造函数的基本介绍(A basic introduction to constructors of classes)
|
SQL PHP 数据库
Yii2.0框架中的Active Record和数据访问对象(DAO)有什么区别?在实际开发中该如何选择?
Yii2.0框架中的Active Record和数据访问对象(DAO)有什么区别?在实际开发中该如何选择?
|
存储 分布式计算 自然语言处理
Hadoop序列化、概述、自定义bean对象实现序列化接口(Writable)、序列化案例实操、编写流量统计的Bean对象、编写Mapper类、编写Reducer类、编写Driver驱动类
Hadoop序列化、概述、自定义bean对象实现序列化接口(Writable)、序列化案例实操、编写流量统计的Bean对象、编写Mapper类、编写Reducer类、编写Driver驱动类
Hadoop序列化、概述、自定义bean对象实现序列化接口(Writable)、序列化案例实操、编写流量统计的Bean对象、编写Mapper类、编写Reducer类、编写Driver驱动类