设计模式(三):策略模式(Strategy)案例分享

策略(Strategy)模式是什么?

Strategy的意思是"策略",指的是一种算法,可以整体替换算法的实现部分,能让我们轻松以不同的算法去解决同一个问题,这种模式就是Strategy模式。


策略(Startegy)模式主要登场角色:

  • Strategy(策略)
    Strategy角色负责决定实现策略所必须的接口(API),可以理解为接口

  • ConcreteStrategy(具体的策略)
    ConcreteStrategy角色负责实现Strategy角色的接口(API),即负责实现具体的策略,可以理解为接口的实现类

  • Context(上下文)
    负责使用Strategy角色,Context角色保存了ConcreteStrategy角色的实例,并使用ConcreteStrategy角色去实现需求,可以理解为需要用到策略接口的入口类

在这里插入图片描述


示例案例:

提示:此案例示例图来自element-ui树形组件:

文件夹可拖拽树形组件

Tree树形组件在这里插入图片描述
在这里插入图片描述

拖拽主要事件:

  • prev —— 放置在目标节点前
  • inner —— 插入至目标节点内
  • next —— 放置在目标节点后

示例代码:

提示:这里只是示例代码,并不是真实实现

文件夹实体Folder


public class Folder {
    private Long id;
    private String name;
    private Long parentId;
    private String path;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getParentId() {
        return parentId;
    }

    public void setParentId(Long parentId) {
        this.parentId = parentId;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }
}

拖拽类型枚举(FolderDragTypeEnum )

public enum FolderDragTypeEnum {
    PREV("folderPrevDragStrategy"),
    INNER("folderInnerDragStrategy"),
    NEXT("folderNextDragStrategy"),
    ;

    private final String serviceName;


    FolderDragTypeEnum(String serviceName) {
        this.serviceName = serviceName;
    }

    public String getServiceName() {
        return serviceName;
    }
}

拖拽策略接口(FolderDragStrategy)

public interface FolderDragStrategy {
    /**
     * 拖拽方法
     *
     * @param originNode(操作的源文件夹)
     * @param targetNode(操作的目标文件夹)
     */
    void drag(Folder originNode, Folder targetNode);
}

文件夹向前拖拽策略实现FolderPrevDragStrategyImpl

@Service("folderPrevDragStrategy")
public class FolderPrevDragStrategyImpl implements FolderDragStrategy {

    @Override
    public void drag(Folder originNode, Folder targetNode) {
        System.out.println("拖拽源文件夹 到 目标文件夹前面开始...");
        //TODO
        System.out.println("拖拽源文件夹 到 目标文件夹前面结束...");
    }
}

文件夹拖到里面策略实现FolderInnerDragStrategyImpl

@Service("folderInnerDragStrategy")
public class FolderInnerDragStrategyImpl implements FolderDragStrategy {

    @Override
    public void drag(Folder originNode, Folder targetNode) {
        System.out.println("拖拽源文件夹 到 目标文件夹里面开始...");
        //TODO
        System.out.println("拖拽源文件夹 到 目标文件夹里面结束...");
    }

文件夹向后拖拽策略实现(FolderNextDragStrategyImpl )

@Service("folderNextDragStrategy")
public class FolderNextDragStrategyImpl implements FolderDragStrategy {

    @Override
    public void drag(Folder originNode, Folder targetNode) {
        System.out.println("拖拽源文件夹 到 目标文件夹后面开始...");
        //TODO
        System.out.println("拖拽源文件夹 到 目标文件夹后面结束...");
    }
}

需要用到拖拽策略的上下文context
这里是我的对外提供的接口FoldDragServiceImpl

@RestController("fold")
public class FoldDragServiceImpl {

    //spring会将实现同一策略接口的所有策略实现类放到map
    @Autowired
    private Map<String , FolderDragStrategy> folderDragStrategyMap;

    @Autowired
    private FolderMapper folderMapper;

    @PutMapping("drag")
    public void dragFolder(@RequestBody FolderDragCommand command){
        Folder originFolder = folderMapper.getById(command.getOriginId());
        Folder targetFolder = folderMapper.getById(command.getTargetId());

        FolderDragStrategy folderDragStrategy = folderDragStrategyMap.get(command.getDragType().toString());
        folderDragStrategy.drag(originFolder , targetFolder);
    }
}


总结

策略模式非常实用,可以替换很多if else,比如上面代码如果要用if else 实现那么可能要写3个判断执行对应方法
使用策略模式可以提高代码可读性,方便后面随着业务扩展,代码不断调整

@RestController("fold")
public class FoldDragServiceImpl {

    //spring会将实现同一策略接口的所有策略实现类放到map
    @Autowired
    private Map<String, FolderDragStrategy> folderDragStrategyMap;

    @Autowired
    private FolderMapper folderMapper;

    @PutMapping("drag")
    public void dragFolder(@RequestBody FolderDragCommand command) {
        if (FolderDragTypeEnum.PREV == command.getDragType()) {
            new FolderPrevDragStrategyImpl().drag(originFolder, targetFolder);
        } else if (FolderDragTypeEnum.INNER == command.getDragType()) {
            new FolderInnerDragStrategyImpl().drag(originFolder, targetFolder);
        } else if (FolderDragTypeEnum.NEXT == command.getDragType()) {
            new FolderNextDragStrategyImpl().drag(originFolder, targetFolder);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农阿福

看明白的同学,别忘请阿福喝奶茶

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值