java设计者模式:策略模式

策略模式的作用在于方便代码维护以及扩展性。

策略模式主要包含三个元素:上下文对象、策略接口、策略实现类

举一个常见的例子:支付功能,支付的方式存在微信、支付宝、银行卡等等。假设项目开始客户只需要微信支付,那么你只需要正常写微信支付的逻辑即可,后面客户又想要加一个支付宝支付,这时候加个if条件判断,然后加上支付宝的支付逻辑就行,再后面又想加银行卡支付、抖音支付一堆支付,如果一直加if判断也是可以解决的,如果觉得所以支付的逻辑都在if代码块中,导致代码又臭又长,那么可以将各个支付的逻辑提取成方法,这样代码就看起来美观了一些,后面加一种方式就加一个支付方法,同时修改支付功能的主方法中加一个if分支。

使用策略模式,那么就可以避免修改支付功能的主方法,只需要加一个策略接口实现类(相当于新增一个支付方法)。从以上例子来看,策略模式相较于if代码块多一个不需要修改支付功能的主方法的优点(可读性和维护性我认为是看个人习惯)。

再举一个例子:你们的项目需要打包(sdk、jar、war等等)提供给外部(其它系统、其它部门或其它公司等等),还是支付功能,你们只实现了微信支付和支付宝支付,但是外部调用者需要银行卡支付,这时候难道要你们来增加这个支付方法,再打包给他吗?那如果又要加别的支付方法呢?多一个支付方法你们就改一次代码吗?

这个时候,使用策略模式就能解决这个问题,给外部开放策略接口,调用者只需要实现策略类,就可以新增支付方法,调用者想加什么就加什么,不需要你们来操心。这个就是策略模式另一个优点:扩展性,也符合开放 - 封闭原则。

1、策略接口

定义了一个公共接口,所有策略类都必须实现这个接口。

/**
 * 同步指导书文件策略接口
 */
public interface SyncFileStrategy {

    /**
     * 指导书文件关联业务类型
     */
    String getType();

    /**
     * 同步文件
     */
    void sync(SyncFileBo bo);

}

2、策略实现类

实现了策略接口的具体类,每个类都定义了一种具体的策略。

/**
 * 文件策略
 */
@Service
@RequiredArgsConstructor
public class FileSyncFileStrategy implements SyncFileStrategy {


    @Override
    public String getType() {
        return SyncFileType.FILE;
    }

    @Override
    public void sync(SyncFileBo bo) {
        //具体实现
    }

}

/**
 * 任务策略
 */
@RequiredArgsConstructor
@Service
public class TaskSyncFileStrategy implements SyncFileStrategy {

    @Override
    public String getType() {
        return SyncFileType.TASK;
    }

    @Override
    public void sync(SyncFileBo bo) {
       //具体实现
    }

}

/**
 * 用户组策略
 */
@Service
@RequiredArgsConstructor
public class UserGroupSyncFileStrategy implements SyncFileStrategy {

    @Override
    public String getType() {
        return SyncFileType.USER_GROUP;
    }

    @Override
    public void sync(SyncFileBo bo) {
        //具体实现
    }

}

......

3、上下文对象

负责调用具体的策略,并根据客户端的请求选择合适的策略来执行。

/**
 * 同步指导书文件上下文对象
 */
@RequiredArgsConstructor
@Service
public class SyncFileFactory {
    private final Map<String, SyncFileStrategy> map = new ConcurrentHashMap<>();

    private final ApplicationContext applicationContext;

    @PostConstruct
    private void init() {
        Map<String, SyncFileStrategy> beansOfType = applicationContext.getBeansOfType(SyncFileStrategy.class);
        beansOfType.forEach((k, v) -> map.put(v.getType(), v));
    }

    /**
     * 同步文件
     */
    public void sync(SyncFileBo bo) {
        getStrategy(bo.getSyncFileType()).sync(bo);
    }

    public SyncFileStrategy getStrategy(String syncFileType){
        SyncFileStrategy syncFileStrategy = map.get(syncFileType);
        if (syncFileStrategy != null){
            return syncFileStrategy;
        }else {
            throw new ServiceException("错误的策略类型!");
        }
    }

}

4、使用示例

1、注入上下文对象
    @Autowired
    private SyncFileFactory syncFileFactory;
2、在方法中使用
    SyncFileBo syncFileBo = new SyncFileBo();
    syncFileBo.setSyncFileType(SyncFileType.USER_GROUP);
    syncFileFactory.sync(syncFileBo);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值