多继承多实现

调用入口

@Resource(name = "ServiceB")
 // 或者
 //@Autowired
 //@Qualifier("ServiceB")
 private Service service;

 public void main(String[] args) throws Exception {
     service.myTestAction("interfaceC");
 }

抽象类里面的抽象方法

package service;

public abstract class Service {

    public void myTestAction(String param) throws Exception {
        myActionDoSomething(param); // 调用myActionDoSomething这个抽象方法
    }

    // 定义了抽象方法,另外有两个实现类来完成抽象方法的细节逻辑
    public abstract void myActionDoSomething(String param) throws Exception;
}

抽象方法的两个实现类

package service;

import org.springframework.stereotype.Component;

@Component("serviceA")
public class ServiceA extends Service {
    @Override
    public void myActionDoSomething(String param) {
        // do thing 1
        System.out.println("这里是执行 Service A");
        System.out.println(param);
    }
}

第1个实现类serviceA 直接处理业务逻辑(即打印一行日志,当然大家实际项目中肯不是打印一行日志这么简单)
第2个实现类serviceB 它还调用了一个接口,这个接口也是多实现的,这个接口的两个实现类里面的业务逻辑也是打印一行日志。

package service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.context.ApplicationContext;

import java.util.Map;

@Component("serviceB")
public class ServiceB extends Service {

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public void myActionDoSomething(String param) throws Exception {
        // do thing 1
        System.out.println("这里是执行 Service B");

        // 获取接口myTestInterface的全部实现类放进Map
        Map<String, MyTestInterface> map = applicationContext.getBeansOfType(MyTestInterface.class);
        // 从Map中选本次执行需要的那一个
        MyTestInterface myTestInterface = map.get(param); // param = interfaceC 或 interfaceD 决定执行下面哪一个接口实现类
        String text = "tttt";
        myTestInterface.myInterfaceDoSomething(text);
    }

    // 定义一个接口 myTestInterface
    interface MyTestInterface {
        void myInterfaceDoSomething(String text);
    }

    // 接口 myTestInterface 的实现类之一
    @Component("interfaceC")
    class myTestInterfaceC implements MyTestInterface {
        @Override
        public void myInterfaceDoSomething(String text) {
            System.out.println("这里是执行 myTestInterface C ");
        }
    }

    // 接口 myTestInterface 的实现类之一
    @Component("interfaceD")
    class myTestInterfaceD implements MyTestInterface {
        @Override
        public void myInterfaceDoSomething(String text) {
            System.out.println("这里是执行 myTestInterface D ");
        }
    }
}

以上是抽象类和接口的多继承多实现例子,在调用的类里面注入的时候,通过注解的形式注入指定name从而决定走的是哪个一个具体的实现类。子实现通过@Component或@Service表明自己唯一的name。
可以用来处理,不同地方调用统一的入口却走的是不一样的逻辑。

注意点:

  1. 关于MyTestInterface myTestInterface = map.get(param);这里的param参数, 调用入口是写死的"interfaceC",而实际中大可能是查询配置表再传递。
  2. class myTestInterfaceC implements MyTestInterface可以写很多个每个里面的逻辑都不一样,但 @Component("interfaceC")注解里面的值interfaceC切不可重复,因为bean无法重复注入。即使启动项目不报错,也只会生效一个。
  3. 假如要做多套class myTestInterfaceC implements MyTestInterface代码每套里面的逻辑不一样, 因为是同一个项目中@Component里面的值必须不一样,比如第一套是interfaceC,那第二套可以是interfaceC2,…以此类推。至于传参的时候,弄两张配置表独立开(一张配的interfaceC一张配置的是interfaceC2),两套各用一张表,互不影响。如果一定要公用一张,则第二套在调用处读取配置值后自动给它拼接字符串2成为interfaceC2再进行传递即可,或者在map.get(param+“2”)这里统一拼接。这样第二套就是找注解值为interfaceC2来执行,并不会影响注解值为interfaceC的,两个注解值不一致了也就不会造成重复注入。

猜你喜欢

转载自blog.csdn.net/qq_29539827/article/details/129408578