《Effective Java》笔记-服务提供者框架
静态工厂方法返回的对象所属的类,在编写包含该静态工厂方法的类时可以不必存在。这种灵活的静态工厂方法构成了服务提供者框架(Service Provider Framework)的基础,例如JDBC API。服务提供者框架是指这样一个系统:多个服务提供者实现一个服务(接口),系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来。
服务提供者框架中有四个重要的组件:
- 服务接口(Service Interface),这是提供者实现的。如JDBC的Connection
- 提供者注册API(Provider Registration API),这是系统用来注册提供者实现,让客户端访问它们的。如DriverManager.registerDriver
- 服务访问API(Service Access API),是客户端用来获取服务的实例的。如DriverManager.get
- 服务提供者接口(Service Provider Interface)这些提供者负责创建其服务实现的实例。这是可选的。如Driver
如果没有服务提供者接口,实现就按照类名称注册,并通过反射方式进行实例化。接口优于反射机制强烈建议使用服务提供者接口。
服务提供者框架模式有着无数种变体。例如,服务访问API可以利用适配器(Adapter)模式,返回比提供者需要的更丰富的服务接口。
服务提供者接口
package org.effectivejava.examples.chapter02.item01; public interface Provider {
Service newService();
}
服务接口
package org.effectivejava.examples.chapter02.item01; public interface Service {
// Service-specific methods go here
}
提供者注册API和服务访问API
package org.effectivejava.examples.chapter02.item01; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; public class Services {
private Services() {
} // Prevents instantiation (Item 4) // Maps service names to services
private static final Map<String, Provider> providers = new ConcurrentHashMap<String, Provider>();
public static final String DEFAULT_PROVIDER_NAME = "<def>"; // Provider registration API
public static void registerDefaultProvider(Provider p) {
registerProvider(DEFAULT_PROVIDER_NAME, p);
} public static void registerProvider(String name, Provider p) {
providers.put(name, p);
} // Service access API
public static Service newInstance() {
return newInstance(DEFAULT_PROVIDER_NAME);
} public static Service newInstance(String name) {
Provider p = providers.get(name);
if (p == null)
throw new IllegalArgumentException(
"No provider registered with name: " + name);
return p.newService();
}
}
测试代码
package org.effectivejava.examples.chapter02.item01; public class Test {
public static void main(String[] args) {
// Providers would execute these lines
Services.registerDefaultProvider(DEFAULT_PROVIDER);
Services.registerProvider("comp", COMP_PROVIDER);
Services.registerProvider("armed", ARMED_PROVIDER); // Clients would execute these lines
Service s1 = Services.newInstance();
Service s2 = Services.newInstance("comp");
Service s3 = Services.newInstance("armed");
System.out.printf("%s, %s, %s%n", s1, s2, s3);
} private static Provider DEFAULT_PROVIDER = new Provider() {
public Service newService() {
return new Service() {
@Override
public String toString() {
return "Default service";
}
};
}
}; private static Provider COMP_PROVIDER = new Provider() {
public Service newService() {
return new Service() {
@Override
public String toString() {
return "Complementary service";
}
};
}
}; private static Provider ARMED_PROVIDER = new Provider() {
public Service newService() {
return new Service() {
@Override
public String toString() {
return "Armed service";
}
};
}
};
}
《Effective Java》笔记-服务提供者框架的更多相关文章
- Effective Java笔记一 创建和销毁对象
Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...
- effective java笔记之java服务提供者框架
博主是一名苦逼的大四实习生,现在java从业人员越来越多,面对的竞争越来越大,还没走出校园,就TM可能面临失业,而且对那些增删改查的业务毫无兴趣,于是决定提升自己,在实习期间的时间还是很充裕的,期间自 ...
- Effective java笔记(二),所有对象的通用方法
Object类的所有非final方法(equals.hashCode.toString.clone.finalize)都要遵守通用约定(general contract),否则其它依赖于这些约定的类( ...
- effective java笔记之单例模式与序列化
单例模式:"一个类有且仅有一个实例,并且自行实例化向整个系统提供." 单例模式实现方式有多种,例如懒汉模式(等用到时候再实例化),饿汉模式(类加载时就实例化)等,这里用饿汉模式方法 ...
- Effective java笔记(一),创建与销毁对象
1.考虑用静态工厂方法代替构造器 类的一个实例,通常使用类的公有的构造方法获取.也可以为类提供一个公有的静态工厂方法(不是设计模式中的工厂模式)来返回类的一个实例.例如: //将boolean类型转换 ...
- Effective java笔记(五),枚举和注解
30.用enum代替int常量 枚举类型是指由一组固定的常量组成合法值的类型.在java没有引入枚举类型前,表示枚举类型的常用方法是声明一组不同的int常量,每个类型成员一个常量,这种方法称作int枚 ...
- Effective java笔记(三),类与接口
类与接口是Java语言的核心,设计出更加有用.健壮和灵活的类与接口很重要. 13.使类和成员的可访问性最小化 设计良好的模块会隐藏起所有的实现细节,仅使用API与其他模块进行通信.这个概念称为信息隐藏 ...
- Effective java笔记5--通用程序设计
一.将局部变量的作用域最小化 本条目与前面(使类和成员的可访问能力最小化)本质上是类似的.将局部变量的作用域最小化,可以增加代码的可读性和可维护性,并降低出错的可能性. 使一个局部变量的作用 ...
- Effective java笔记3--类和接口2
三.接口优于抽象类 java提供两种机制,可以用来定义一个允许多个实现的类型:接口和抽象类.由于java只允许单继承,所以,抽象类作为类型定义受到了极大的限制. 已有的类可以很容易被更新,以实现新的接 ...
随机推荐
- xdoj新生现场赛1269——带有限制条件的bfs 寻找最短路径
bfss是解决最短路径的强大武器 (尝试dfs寻找最短路径 -(7*7)就会爆炸) 例题1 ccf 201604-4 游戏 问题描述 小明在玩一个电脑游戏,游戏在一个n×m的方格图上进行,小明控制 ...
- 《DSP using MATLAB》Problem 5.15
代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...
- python数据类型及字符编码
一.python数据类型,按特征划分 1.数字类型 整型:布尔型(True,False).长整型(L),会自动帮你转换成长整型.标准整型 2.序列类型 字符串(str).元组(tuple).列表(li ...
- 【Hi3516】 uboot下烧写BSP
setenv serverip xx.xx.xx.xx setenv ipaddr xx.xx.xx.xx setenv ethaddr xx:xx:xx:xx:xx:xx setenv netmas ...
- mongo之 前后台创建索引 --noIndexBuildRetry
在数据量超大的情形下,任何数据库系统在创建索引时都是一个耗时的大工程.MongoDB也不例外.因此,MongoDB索引的创建有两个选择,一个是前台方式,一个是后台方式.那这两种方式有什么差异呢,在创建 ...
- 原生js实现的瀑布流布局
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- enum和数据库entity互转
注意,code和desc都是string的,数据库的entity是integer,dto的是enum,所以需要一个转换 entity转dto EnumGender.getEnum(String.val ...
- 关于adaboost分类器
我花了将近一周的时间,才算搞懂了adaboost的原理.这根骨头终究还是被我啃下来了. Adaboost是boosting系的解决方案,类似的是bagging系,bagging系是另外一个话题,还没有 ...
- VS2010生成安装包制作步骤 (转)
阅读目录 VS2010生成安装包制作步骤 回到目录 VS2010生成安装包制作步骤 在VS2010中文旗舰版本中生成winForm安装包,可以复制你电脑中的开发环境,避免你忘记了一下配置然后在别的 ...
- 【MatConvNet代码解析】 一些理解
1.DagNN对象的executionOrder属性 该属性是hidden属性,所以外部是访问不到的.只有dagnn.DagNN类和dagnn.Layer类可以访问到. 该属性的设置是在DagNN类的 ...