服务提供者

服务提供者框架

1.什么是服务提供者框架

服务提供者框架是指:多个服务提供者实现一个服务,系统为客户端提供多个实现,并把他们从多个实现中解耦出来。服务提供者的改变对它们的客户端是透明的,这样提供了更好的可扩展性。例如,JDBC,JMS等就是用了服务提供者框架 服务提供者框架是指:多个服务提供者实现一个服务,系统为客户端提供多个实现,并把他们从多个实现中解耦出来。服务提供者的改变对它们的客户端是透明的,这样提供了更好的可扩展性。例如,JDBC,JMS等就是用了服务提供者框架。

2.服务提供者关系图

image.png

略讲JDBC

Class.forName("com.mysql.jdbc.Driver");   
DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123");  
从这个地方可以看出:我们只需要更换数据库的驱动名称与建立连接的URL,用 
户名等信息,就可以完全切换到另外一个数据库。数据库底部怎么操作的我们不 
清楚,也没必要清楚。我们获取的连接对象是Connection,查看 
java.sql.Connection这个类,会发现它只是一个接口。我们得到的只是一个接口, 

怎么可能能够操作数据库呢?其实这里得到的不是Connection接口,而是它的一个
实现类,只是对于客户端不可见而已。这可能就是所谓的面向接口编程,客户端只
需要知道它该知道的信息,服务端告诉客户端,你可以调用哪些方法。至于具体方
法怎么实现是服务端的事情,客服端就不需要管,也不需要知道了。

 下面我们看看简单的这2个语句分别做了什么事情:
 语句一: Class.forName("...")。这样一个语句会实例化一个 
 com.mysql.jdbc.Driver类(提供服务者实现类),并将这个类的实例注册到 
DriverManager(服务提供者注册类)。
 语句二: 通过建立连接的URL,用户名,密码来获取建立到mysql数据库的连     
 接。是这样的,DriverManager通过你传进来的url信息判断出你是要获取那个服务 
 提供者提供的服务。也就是语句一已经将提供服务者实现类注册到DriverManager     
了,DriverManager获取到这个服务提供者实现类对象之后,通过调用它的     
getService(mysql里面是connect方法)方法获取到服务具体实现类对象,返回的 
却是java.sql.Connection接口对象(因为服务具体实现类实现了Connection接 
口),这样把服务具体实现类对象隐藏了。提供了很好的扩展性。

3.详解

  1. 服务接口(Service Interface)
    在服务接口里面定义一些提供具体服务的方法,假设我们需要实现进出地铁的服务SubWayService,这个服务接口中一定有in(),out()方法,我们之后再创建这个服务接口的具体的实现类去实现lin(),out()方法.

  2. 服务提供者接口(Service Provider Interface)
    服务提供者接口顾名思义就是定义提供什么样的服务的方法.我们在上面提供了一个服务接口,在这里就要提供一个能获取'注册登陆'服务的方法.
    例如 : getSubWayrService() 返回值 为SubWayServiceInterface
    然后去创建实现服务提供者接口的具体实现类实现getUserService()方法.

  3. 提供者注册API(Provider Registration API)
    服务提供者接口的具体实现类里面去注册这个API,在类的静态初始块中去注册API,因为只有注册了API,才能享受服务.这些注册过的API交给ServiceManager管理.

  4. 服务访问API(Service Acess API)
    既然已经注册了API,那我们就可以向ServiceManager申请具体的服务,调用服务实例的方法.
    服务访问API是灵活的静态工厂,它构成了服务提供者框架的基础.

4实例 (一卡通为例,一次性相同的步骤)

以地铁进出控制为例:现在北铁进出都是刷卡,有二种卡:1.一卡通(比如一次性冲值50元,进地铁刷一次,出地铁刷一次,扣2元)。2.一次性卡(进地铁刷一次,出地铁插入回收。)这2种卡都可以实现进出地铁功能,但实现的具体方法是有区别的:一卡通:需要获取这卡余额是多少,然后扣掉2元。如果余额不足2元怎么处理等。一次性卡则没必要了。
1.整体框架

image.png

2.首先服务接口 和服务提供者接口

package serviceProvider;
/**
 * @author frank
 * @version 1.0
 * @project practice
 * @description 进出地铁服务接口
 * @date 2023/8/12 09:48:23
 */
public interface SubWayServiceInterface {
    //进入地铁
    public boolean in();

    //出地铁
    public boolean out();
}

服务提供者接口

package serviceProvider;

/**
 * @author frank
 * @version 1.0
 * @project practice
 * @description 地铁进出服务提供者接口
 * @date 2023/8/12 09:48:23
 */
public interface SubwayProviderInterface {
    public SubWayServiceInterface getSubwayService();
}

3.当有了接口过后,不同的服务提供者可以实现接口,来实现不同方法体,在这里我把两个文件写在一起

#SubWayProviderImpl.java
package serviceProvider.oneCard;
import serviceProvider.ServiceManager;
import serviceProvider.SubWayServiceInterface;
import serviceProvider.SubwayProviderInterface;

/**
 * @author frank
 * @version 1.0
 * @project practice
 * @description 地铁进出服务提供者接口实现类
 * @date 2023/8/12 09:48:23
 */
public class SubWayProviderImpl implements SubwayProviderInterface {
    //static 只会访问一次  第一次反射的时候可以访问一次,后面再次new的就不会访问了
    static {
        ServiceManager.registerProvider("一卡通",new SubWayProviderImpl());
    }
    @Override
    public SubWayServiceInterface getSubwayService() {
        return new SubWayServiceImpl();
    }
}


#SubWayServiceImpl.java
package serviceProvider.oneCard;
import serviceProvider.SubWayServiceInterface;
/**
 * @author frank
 * @version 1.0
 * @project practice
 * @description 进出地铁服务接口实现类
 * @date 2023/8/12 09:48:23
 */
public class SubWayServiceImpl implements SubWayServiceInterface {
    @Override
    public boolean in() {
        //TODO
        System.out.println("这是一卡通in:AAAAAA");
        return false;
    }

    @Override
    public boolean out() {
        //TODO
        System.out.println("这是一卡通out:BBBBBB");
        return false;
    }
}

4.如何管理不同的服务提供商,这个就需要同一个管理,就需要一个ServiceManager,向ServiceManager注册自己的API,并由ServiceManger同一个管理和调用。

package serviceProvider;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author frank
 * @version 1.0
 * @project practice
 * @description 服务提供者注册类
 * @date 2023/8/12 09:48:23
 */
public class ServiceManager {
    private ServiceManager() {

    }

    private static final Map<String, SubwayProviderInterface> providers = new ConcurrentHashMap<String, SubwayProviderInterface>();

    public static void registerProver(String name, SubwayProviderInterface p) {
    //添加不同的服务提供商的API,并只生成一次,永久添加的是Provider。
        providers.put(name, p);
    }

    public static SubWayServiceInterface getSubWayService(String name) {
        SubwayProviderInterface p = providers.get(name);
        //如果没有添加就进行访问就报错
        if (p == null) {
            throw new IllegalArgumentException(
                    "No provider registered with name:" + name);
        }
        return p.getSubwayService();
    }
}

5.测试类
在通过类路径反射进行生成类的时候,会调用该类的static代码体里面代码,进行API的注册,这样就可以保持Provider只注册一次,任何时候就可以使用。最后通过Name,获取到对应的实例。

package serviceProvider;
public class text {
    public static void main(String[] args) throws ClassNotFoundException {
        //反射,调用类,而不是用实例化,向ServiceManager进行注册API
        Class.forName("serviceProvider.oneCard.SubWayProviderImpl");
        SubWayServiceInterface swi = ServiceManager.getSubWayService("一卡通");
        swi.in();
        swi.out();
    }
}

最后这里可以看到输出效果:


image.png

参考链接:https://blog.csdn.net/MIMOCH/article/details/102476314

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容