ServiceLoader服务提供者模式,实现动态插件加载,类责任链模式

简介: <div style="margin:0px; padding:0px; border:0px; line-height:1.428571em; font-family:Helvetica,Arial,'Droid Sans',sans-serif; font-size:14.4444446563721px"> <del style="margin:0px; padding:0px; b
+关注继续查看

ServiceLoader服务提供者模式,实现动态插件加载,类责任链模式

ServiceLoader的功能比ClassLoader简单,它可以帮我们获取所有实现了某接口或基类的类。当然前提是ClassLoader已经加载过的类。举个例子:
定义一个接口:

public interface IService {  
    public String sayHello();  

    public String getScheme();  
}

以及两个实现类:

public class HDFSService implements IService {  

    @Override  
    public String sayHello() {  
        return "Hello HDFS!!";  
    }  

    @Override  
    public String getScheme() {  
        return "hdfs";  
    }  
}

public class LocalService implements IService {  

    @Override  
    public String sayHello() {  
        return "Hello Local!!";  
    }  

    @Override  
    public String getScheme() {  
        return "local";  
    }  

}

将 HDFSService 和 LocalService 打包成 jar,java包的 META-INFO/services 下以IService这个类的全名来新建立一个文件,文件中的内容为两个实现类的全名:

org.hadoop.java.HDFSService
org.hadoop.java.LocalService

我们通过一下方式来调用对应的实现类:

public class ServiceLoaderTest {  
    public static void main(String[] args) {  
        //need to define related class full name in /META-INF/services/....  
        ServiceLoader<IService> serviceLoader = ServiceLoader  
                .load(IService.class);  
        for (IService service : serviceLoader) {  
            System.out.println(service.getScheme()+"="+service.sayHello());  
        }  
    }  

}

插件模式

Netbean的插件就是使用ServiceLoader动态加载。先用类加载器将新的插件jar包加载到JVM,然后就可以使用ServiceLoader调用。

类责任链模式

有时候我们的程序需要根据匹配的条件,执行某段代码,如:

if (optionA) {
    if (optionB) {
        doSomething1();
    } else {
        doSomething2();
    }
} else {
    doSomething3();
}

直接用if else条件判断,比较复杂,不好维护。
类似上面的代码,根据不同的输入选项或命令行参数等调用不同的方法来完成某些操作,而不是单纯的返回数据。因此,这些选项是为了确定现在这个request是谁的职责,而这正是“责任链模式”要解决的问题!本节的标题为“类责任链模式”,表示我的解决方案是类似“责任链模式”,并不严格和它保持一致,但核心思想是一致的:使多个对象都有机会处理请求。

因此,每个RequestHandler都需提供一个接口判断自己能否处理当前请求;如果能处理,则Client调用另一个执行的接口:

public interface Handler {
    public boolean accept(Properties options);
    public void execute();
}

于是,上面的分支结构对应三个独立的Handler类:

public class RequestHandler1 implements Handler {
    public boolean accept(Properties options) {
        return options.getProperty("A") != null
            && options.getProperty("B") != null;
    }

    public void execute() {
        doSomething1();
    }
}

public class RequestHandler2 implements Handler {
    public boolean accept(Properties options) {
        return options.getProperty("A") != null
            && options.getProperty("B") == null;
    }

    public void execute() {
        doSomething2();
    }
}

public class RequestHandler3 implements Handler {
    public boolean accept(Properties options) {
        return options.getProperty("A") == null;
    }

    public void execute() {
        doSomething3();
    }
}

接下来还需要一个额外的管理类负责这些类的实例化的请求的分发:

import java.util.ServiceLoader;
import java.util.Iterator;

public class Manager {
    private static Arraylist;
    static {
        list = new Array();

        ServiceLoaderloader = ServiceLoader.load(Handler.class);
        Iteratorit = loader.iterator();
        while (it.hasNext()) {
            list.add(it.next());
        }
    }

    public static void process(Properties options) {
        for (Handler handler : list) {
            if (handler.accept(options)) {
                handler.execute();
            }
        }
    }
}

上面代码使用了服务加载功能自动实例化所有注册过的Handler子类,如果你还不了解它的原理,可查看相应的API文档。有了这些代码,已经万事具备!也许你已经发现,这样的设计和JDBC的接口不谋而合:Manager对应java.sql.DriverManager、Handler对应java.sql.Driver、RequestHandler这些类则对应数据库厂商自己实现的驱动程序。

基于这样的框架,它的代码总量也许比原来的要多,但你不再需要在一堆if else中仔细推敲代码执行的前提条件,所有的前提条件都在accept函数里;添加新的功能所要做的仅需实现一个新的类,无须修改现有代码,符合开闭原则。

Reference

类责任链模式
转一篇很不错的介绍NetBeans的文章
http://blog.csdn.net/kokojhuang/article/details/8273303


目录
相关文章
|
18天前
|
Java
Java反射机制动态操作
Java反射机制动态操作
13 0
|
21天前
|
Java API Apache
springboot 调用外部接口的21种方式
springboot 调用外部接口的21种方式
27 0
|
2月前
|
Dubbo Java 应用服务中间件
SpringBoot 调用外部接口的三种方式
SpringBoot 调用外部接口的三种方式
|
2月前
|
设计模式 存储 Java
Java版事件与委托实现自动创建工厂并热加载
Java版事件与委托实现自动创建工厂并热加载
Java版事件与委托实现自动创建工厂并热加载
|
2月前
|
设计模式
实现生成工厂代码,实现热加载
实现生成工厂代码,实现热加载
|
10月前
|
uml
工厂模式+配置文件+反射实现数据访问程序
工厂模式+配置文件+反射实现数据访问程序
55 0
工厂模式+配置文件+反射实现数据访问程序
|
11月前
|
缓存
读源码长知识 | 动态扩展类并绑定生命周期的新方式
在阅读viewModelScope源码时,发现了一种新的方式。 协程需隶属于某 CoroutineScope ,以实现structured-concurrency,而 CoroutineScope 应
95 0
【Groovy】MOP 元对象协议与元编程 ( Expando 动态类 | 创建动态类 | 为动态类增加字段和方法 )
【Groovy】MOP 元对象协议与元编程 ( Expando 动态类 | 创建动态类 | 为动态类增加字段和方法 )
127 0
【Groovy】MOP 元对象协议与元编程 ( Expando 动态类 | 创建动态类 | 为动态类增加字段和方法 )
|
Java Android开发 开发者
【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )
【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )
118 0
|
设计模式 Java 索引
【设计模式】代理模式 ( 动态代理使用流程 | 创建目标对象 | 创建被代理对象 | 创建调用处理程序 | 动态创建代理对象 | 动态代理调用 )
【设计模式】代理模式 ( 动态代理使用流程 | 创建目标对象 | 创建被代理对象 | 创建调用处理程序 | 动态创建代理对象 | 动态代理调用 )
85 0
【设计模式】代理模式 ( 动态代理使用流程 | 创建目标对象 | 创建被代理对象 | 创建调用处理程序 | 动态创建代理对象 | 动态代理调用 )
相关产品
云迁移中心
推荐文章
更多