策略模式及结合spring中InitializingBean在工作中的使用案例简介

策略模式简介

策略模式定义了一系列的算法,并将每一个算法封装起来,且使他们可以相互替换,让算法独立于使用它的客户而独立变化。

在这里插入图片描述

主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:实现同一个接口。

Spring中InitializingBean接口简介

InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet一个方法,凡是实现该接口的类,
在初始化bean的时候都会执行该方法。

工作中使用案例简介

背景简介

实际工作中,平台需要根据不同的标注模板类型,维护不同的标注标签。
梳理后整理标注模板类型大概有10种:
1-单图单标签
2-单图多标签
3-矩形框标注
......
......
10-文本实体抽取
针对每种类型,其标注时使用的标签格式是不同的(
如单选框、多选框、矩形框、多边形框等),要针对不用的类型,
实现其标签的生成和标签项目的增加或删除功能,伪代码如下:
	if 1-单图单标签
		if 不存在
			生成规则
		if 新增标签项
		   xxxx
		if 删除标签项
		   xxxx
	if 2-单图多标签
		if 不存在
			生成规则
		if 新增标签项
		   xxxx
		if 删除标签项
		   xxxx
	if 3-矩形框标注
		if 不存在
			生成规则
		if 新增标签项
		   xxxx
		if 删除标签项
		   xxxx
	if 4-
		
	if 5-
	......
	......
	if 10-文本实体抽取
		xxxxx
	
		从以上伪代码发现,if太多了。另外如果某一个标签模板逻辑有变化,或者再增加
	一个类 型,都需要对该代码进行修改。可维护性之差可想而知.
		从面向对象的【开闭原则】上来看,也违反了对扩展开发,对修改关闭的原则。
		
		接下来开始抽取,我们发现不同标签,相同的操作有添加标签项和删除标签项,两种
	操作的本质是对字符串的处理;按照不同的业务逻辑 组装成不同的xml字符串来达到
	前端的不同展现的目的。因此形成以下设计思路。

设计实现

   抽象标签模板接口,并定义增加标签项和删除标签项两个行为方法;每种不同的标签模板编写
自己的实现类,实现接口,按自己的逻辑重写两个方法;另外,定义一个,策略工厂类,记录每种
类型和其实现类的映射关系,对外提供注册和获取两个方法。在实现类加载时进行注册,在
业务使用时,按类型进行获取。

1.定义标签接口

定义标签接口,定义增加标签和删除标签两个方法。

public interface LabelTemplateService {

    String addLabel(View view, String labelValue,String backgroud);

    String removeLabel(View view, String labelValue);

}

2.编写策略工厂类

编写工厂类,定义一个key为标签类型标识,value为标签具体实现类的map,提供两个方法,一个是注册方法,在实现类加载时进行注册,put到map中;另一个是获取value的方法,在业务使用的地方调用,根据传入的key的类型值,获取具体的实现类。

public class LabelTemplateStrategyFactory {
    private LabelTemplateStrategyFactory(){}
    private static Map<String, LabelTemplateService> services = new ConcurrentHashMap<>();

    public static LabelTemplateService getByTemplate(String template) {
        return services.get(template);
    }

    public static void register(String template, LabelTemplateService labelTemplateService) {
        services.put(template, labelTemplateService);
    }
}

3.编写具体标签实现类

编写具体实现类,实现LabelTemplateService 和InitializingBean接口,每个实现类按具体业务逻辑对LabelTemplateService的addLabel和removeLabel方法进行重写;重写InitializingBean的afterPropertiesSet方法,来实现具体类的注册功能。

1)图像分类-单图单标签

@Service
public class ImageClassifySingleLabelServiceImpl implements LabelTemplateService, InitializingBean {
    @Override
    public String addLabel(View view, String labelValue,String background) {
        
        // 具体逻辑
        // ......

        return XMLUtil.convertToXml(view);
    }

    @Override
    public String removeLabel(View view, String labelValue) {
        
        // 具体逻辑
        // ......
        return XMLUtil.convertToXml(view);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    	//key(类型)为1,value(实现类) 为本身   把类型和本身对象进行注册
        LabelTemplateStrategyFactory.register("1", this);
    }
}

2)图像-物体检测

@Service
public class ImageObjDetecRectLabelServiceImpl implements LabelTemplateService, InitializingBean {
    @Override
    public String addLabel(View view, String labelValue,String backgroud) {
        
 		// 具体逻辑
        // ......
        return XMLUtil.convertToXml(view);
    }

    @Override
    public String removeLabel(View view, String labelValue) {
       
        // 具体逻辑
        // ......
        
        return XMLUtil.convertToXml(view);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        // 3 物体检测
        LabelTemplateStrategyFactory.register("3", this);
    }
}

3)…
4)…

10)…
这里每个具体实现类都实现接口,重写接口的行为方法。

4.业务调用示例

		// xxxx 
		// 取出已有的标签配置
		String labelConfig = project.getLabelConfig();
        View view = (View) XMLUtil.convertXMLToObject(View.class, labelConfig);
        String xmlView = "";
        // 标签模板 1单图单标签 2单图多标签 3 4 5 等等
        String labelTemplate = dataSetPO.getLabelTemplate().toString();
        // 使用工厂类来获取对应的标签模板
        LabelTemplateService templateService = LabelTemplateStrategyFactory.getByTemplate(labelTemplate);

        if (DataConstants.LABEL_STUDIO_LABEL_OPT_ADD.equals(opt)) {
            xmlView = templateService.addLabel(view, labelValue, backgroud);// 增加标签
        } else if (DataConstants.LABEL_STUDIO_LABEL_OPT_REMOVE.equals(opt)) {
            xmlView = templateService.removeLabel(view, labelValue);// 删除标签
        }
        // 获取到 处理完的 xmlView 继续后续处理

效果总结

	通过以上的设计实现,我们消灭了大部分的if-else,达到解耦,使代码更加简洁清晰。同时
符合对修改关闭,对扩展开放的原则;如果新增一种标签模板,我们不用去修改原有代码,而是
扩展一个实现类,实现对应的方法;如果某种标签模板逻辑有变更,也是只修改其对应的实现类
即可,而不影响整体结构和其他实现类。
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

祺稷

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值