莫大人

1-多实现-接口管理

1、背景

在实际的项目开发过程中,经常会遇到同一个业务操作不同场景时的不同业务逻辑,这个时候为了使系统拥有更高的可扩展性,可维护性,基于此背景开发了这套框架。
1、使用ServiceManager统一管理接口实例
2、使用ExecuteService统一接口实现,单一职责
3、可选AbstractExecuteServiceTemplate,使用它实现接口逻辑模板化,模板模式
4、可选ExecuteCommonService,接口实例通过聚合ExecuteCommonService达到代码复用的目的。合成复用原则。

1.1、以前

    @Autowired
    private AService aService;
    @Autowired
    private BService bService;
    @Autowired
    private CService cService;
    @Autowired
    private DService dService;

    @Test
    public void testOld() {
        // 以往我们的多场景实现可能是这样
        TestReq req = new TestReq();
        TestRsp rsp = null;
        if (场景A) {
            rsp = aService.execute(req);
        }

        if (场景B) {
            rsp = bService.execute(req);
        }

        if (场景C) {
            rsp = cService.execute(req);
        }

        if (场景D) {
            rsp = dService.execute(req);
        }

    }

1.2、现在

        TestReq req = new TestReq();
        ExecuteService<TestReq, TestRsp> serviceA = ServiceManager.getService(ServiceEnum.SERVICE_A, ServiceTypeEnum.TEST_SERVICE_A);
        TestRsp rspA = serviceA.execute(req);

2、类图

image

核心接口为:ExecuteService,提供业务执行的入口;
接口实例管理器:ServiceManager,提供本地接口实例管理;
提供两种实现方式:
1、绿色标识为简单模式,适合接口逻辑比较独立,没有耦合的情况。
2、蓝色标识为复杂模式,ExecuteServiceTemplate将ExecuteService的execute方法模板化,规范ExecuteService实现。
额外提供一种代码复用的方式:
通过使用ExecuteCommonService将共用代码进行复用,然后聚合到ExecuteService实现中。

3、时序图

image

4、实现

4.1、鱼骨图

image

framework核心包为框架核心,为业务端提供规范与平台。
implement为业务端运用框架需要实现的类。
client为实际调用客户端,这里展示的为测试类。

4.2、framework

4.2.1、ExecuteService

package com.guo.core.framework.template;

import org.springframework.beans.factory.InitializingBean;

public interface ExecuteService<Req,Rsp> extends InitializingBean {

    Rsp execute(Req req);

}

4.2.2、ServiceManager

package com.guo.core.framework.template;

import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

@Slf4j
public class ServiceManager {

    private static final Map<String, Map<String,ExecuteService<?,?>>> serviceMap = new HashMap<>();

    public static void registerService(BizService service, ServiceType serviceType, ExecuteService<?,?> serviceImpl) {
        log.info("服务[{}.{}]注册", service.getCode(),serviceType.getCode());
        if (!serviceMap.containsKey(service.getCode())) {
            Map<String,ExecuteService<?,?>> serviceTypeMap = new HashMap<>();
            serviceTypeMap.putIfAbsent(serviceType.getCode(), serviceImpl);
            serviceMap.putIfAbsent(service.getCode(), serviceTypeMap);
        }

        serviceMap.get(service.getCode()).putIfAbsent(serviceType.getCode(), serviceImpl);
    }

    public static ExecuteService getService(BizService service, ServiceType serviceType) {
        Map<String,ExecuteService<?,?>> serviceTypeMap = serviceMap.get(service.getCode());
        if (serviceTypeMap == null) {
            log.info("服务[{}]不存在", service.getCode());
            return null;
        }
        ExecuteService executeService = serviceTypeMap.get(serviceType.getCode());
        if (executeService == null) {
            log.info("服务[{}.{}]不存在", service.getCode(),serviceType.getCode());
            return null;
        }

        return executeService;
    }

}

4.2.3、Service

package com.guo.core.framework.template;

public interface BizService {

    String getCode();

}

4.2.4、ServiceType

package com.guo.core.framework.template;

public interface ServiceType {

    String getCode();

}

4.3、implement

4.3.1、简单模式

  • 适合场景:适合业务逻辑简单或业务框架不清晰场景。

4.3.1.1、ServiceEnum

  • 定义服务,用于服务注册管理
package com.guo.core.framework.template;

public enum ServiceEnum implements BizService {

    SERVICE_A("SERVICE_A"),
    SERVICE_B("SERVICE_B");

    private final String code;

    ServiceEnum(String code) {
        this.code = code;
    }

    @Override
    public String getCode() {
        return this.code;
    }

}

4.3.1.2、ServiceTypeEnum

  • 定义服务操作类型,用于服务注册管理。
package com.guo.core.framework.template;

public enum ServiceTypeEnum implements ServiceType {

    TEST_SERVICE_A("TEST_SERVICE_A"),
    TEST_SERVICE_B("TEST_SERVICE_B"),
    TEST_SERVICE_C("TEST_SERVICE_C"),
    TEST_SERVICE_D("TEST_SERVICE_D");

    private final String code;

    ServiceTypeEnum(String code) {
        this.code = code;
    }

    @Override
    public String getCode() {
        return this.code;
    }
}

4.3.1.3、TestReq

  • 定义接口请求数据结构体
package com.guo.core.framework.template;

import lombok.Data;

@Data
public class TestReq {

    private String name;

}

4.3.1.4、TestRsp

  • 定义接口响应数据结构体
package com.guo.core.framework.template;

public class TestRsp {
}

4.3.1.5、AService

  • 模拟简单模式A服务.A类型
package com.guo.core.framework.template.simple;

import com.guo.core.framework.template.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class AService extends AbstractExecuteService<TestReq, TestRsp> {

    @Autowired
    private ExecuteCommonService executeCommonService;

    @Override
    protected ServiceType getServiceType() {
        return ServiceTypeEnum.TEST_SERVICE_A;
    }

    @Override
    protected BizService getService() {
        return ServiceEnum.SERVICE_A;
    }

    @Override
    public TestRsp execute(TestReq testReq) {
        log.info("执行AService");
        return executeCommonService.commonService(testReq);
    }
}

4.3.1.5、BService

  • 模拟简单模式B服务.B类型
package com.guo.core.framework.template.simple;

import com.guo.core.framework.template.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class BService extends AbstractExecuteService<TestReq, TestRsp> {

    @Autowired
    private ExecuteCommonService executeCommonService;

    @Override
    protected ServiceType getServiceType() {
        return ServiceTypeEnum.TEST_SERVICE_B;
    }

    @Override
    protected BizService getService() {
        return ServiceEnum.SERVICE_B;
    }

    @Override
    public TestRsp execute(TestReq testReq) {
        log.info("执行BService");
        return executeCommonService.commonService(testReq);
    }
}

4.3.1.6、ExecuteCommonService

  • [可选]接口公共服务,用于代码复用
package com.guo.core.framework.template;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class ExecuteCommonService {

    public TestRsp commonService(TestReq testReq) {
        log.info("执行公共服务:commonService");
        return new TestRsp();
    }

}

4.3.1.7、集成测试

    @Test
    public void testSimple() {
        // 简单模式
        TestReq req = new TestReq();
        ExecuteService<TestReq, TestRsp> serviceA = ServiceManager.getService(ServiceEnum.SERVICE_A, ServiceTypeEnum.TEST_SERVICE_A);
        TestRsp rspA = serviceA.execute(req);

        ExecuteService<TestReq, TestRsp> serviceB = ServiceManager.getService(ServiceEnum.SERVICE_B, ServiceTypeEnum.TEST_SERVICE_B);
        TestRsp rspB = serviceB.execute(req);

    }

4.3.2、复杂模式

  • 适合场景:业务复杂且业务框架清晰。

4.3.2.1、ServiceEnum

  • 定义服务,用于服务注册管理
package com.guo.core.framework.template;

public enum ServiceEnum implements BizService {

    SERVICE_A("SERVICE_A"),
    SERVICE_B("SERVICE_B");

    private final String code;

    ServiceEnum(String code) {
        this.code = code;
    }

    @Override
    public String getCode() {
        return this.code;
    }

}

4.3.2.2、ServiceTypeEnum

  • 定义服务操作类型,用于服务注册管理。
package com.guo.core.framework.template;

public enum ServiceTypeEnum implements ServiceType {

    TEST_SERVICE_A("TEST_SERVICE_A"),
    TEST_SERVICE_B("TEST_SERVICE_B"),
    TEST_SERVICE_C("TEST_SERVICE_C"),
    TEST_SERVICE_D("TEST_SERVICE_D");

    private final String code;

    ServiceTypeEnum(String code) {
        this.code = code;
    }

    @Override
    public String getCode() {
        return this.code;
    }
}

4.3.2.3、TestReq

  • 定义接口请求数据结构体
package com.guo.core.framework.template;

import lombok.Data;

@Data
public class TestReq {

    private String name;

}

4.3.2.4、TestRsp

  • 定义接口响应数据结构体
package com.guo.core.framework.template;

public class TestRsp {
}

4.3.2.5、CService

  • 模拟复杂模式A服务.C类型
package com.guo.core.framework.template.complex;

import com.guo.core.framework.template.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class CService extends ExecuteServiceTemplate {

    @Autowired
    private ExecuteCommonService executeCommonService;

    @Override
    protected ServiceType getServiceType() {
        return ServiceTypeEnum.TEST_SERVICE_C;
    }

    @Override
    protected BizService getService() {
        return ServiceEnum.SERVICE_A;
    }

    @Override
    protected void after(TestReq testReq, TestRsp testRsp) {
        log.info("执行CService.after");
    }

    @Override
    protected TestRsp post(TestReq testReq) {
        log.info("执行CService.post");
        return executeCommonService.commonService(testReq);
    }

    @Override
    protected void before(TestReq testReq) {
        log.info("执行CService.before");
    }
}

4.3.2.5、DService

  • 模拟复杂模式B服务.D类型
package com.guo.core.framework.template.complex;

import com.guo.core.framework.template.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class DService extends ExecuteServiceTemplate {

    @Autowired
    private ExecuteCommonService executeCommonService;

    @Override
    protected ServiceType getServiceType() {
        return ServiceTypeEnum.TEST_SERVICE_D;
    }

    @Override
    protected BizService getService() {
        return ServiceEnum.SERVICE_B;
    }

    @Override
    protected void after(TestReq testReq, TestRsp testRsp) {
        log.info("执行DService.after");
    }

    @Override
    protected TestRsp post(TestReq testReq) {
        log.info("执行DService.post");
        return executeCommonService.commonService(testReq);
    }

    @Override
    protected void before(TestReq testReq) {
        log.info("执行DService.before");
    }
}

4.3.2.6、ExecuteServiceTemplate

  • 业务模板,定义业务逻辑框架
package com.guo.core.framework.template.complex;

import com.guo.core.framework.template.AbstractExecuteService;
import com.guo.core.framework.template.TestReq;
import com.guo.core.framework.template.TestRsp;

public abstract class ExecuteServiceTemplate extends AbstractExecuteService<TestReq, TestRsp> {

    @Override
    public TestRsp execute(TestReq testReq) {
        this.before(testReq);
        TestRsp testRsp = this.post(testReq);
        this.after(testReq, testRsp);
        return testRsp;
    }

    protected abstract void after(TestReq testReq, TestRsp testRsp);

    protected abstract TestRsp post(TestReq testReq);

    protected abstract void before(TestReq testReq);

}

4.3.2.7、ExecuteCommonService

  • [可选]接口公共服务,用于代码复用
package com.guo.core.framework.template;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class ExecuteCommonService {

    public TestRsp commonService(TestReq testReq) {
        log.info("执行公共服务:commonService");
        return new TestRsp();
    }

}

4.3.2.8、集成测试

    @Test
    public void testTemplate() {
        // 模板模式
        TestReq req = new TestReq();
        ExecuteService<TestReq, TestRsp> serviceC = ServiceManager.getService(ServiceEnum.SERVICE_A, ServiceTypeEnum.TEST_SERVICE_C);
        TestRsp rspC = serviceC.execute(req);

        ExecuteService<TestReq, TestRsp> serviceD = ServiceManager.getService(ServiceEnum.SERVICE_B, ServiceTypeEnum.TEST_SERVICE_D);
        TestRsp rspD = serviceD.execute(req);

    }

posted on 2021-12-24 13:48  莫大人  阅读(77)  评论(0编辑  收藏  举报

导航