第二章 创建与销毁对象
1、考虑用静态工厂方法代替构造器
优点:
1、有名称
2、不必在每次调用他们的时候都创建一个新的对象
3、他们可以返回原返回类型的任何子类型对象
4、使代码更简洁
缺点:
1、类如果不含公有的或者受保护的构造器,就不能被子类化
2、与其他的静态方法实际上没有任何区别,不能一眼就看出来
可以用一些惯用的名称:
valueOf
Of
getInstance
newInstance
getType
NewType
关于第三条优点,这种灵活的静态工厂方法可以构成 服务者提供框架(Service Provider Framework)
/**
* 服务提供者框架
* 多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来
*/
public class Services {
private Services(){
}
private static final String DEFAULT_PROVIDER = "DEFAULT_PROVIDER";
private static final ConcurrentHashMap<String,Provider> providers = new ConcurrentHashMap();
/**
* 注册提供者
* @param name
* @param provider
*/
public static void registProvider(String name,Provider provider){
providers.put(name,provider);
}
/**
* 注册默认提供者
* @param provider
*/
public static void registDefaultProvider(Provider provider){
providers.put(DEFAULT_PROVIDER,provider);
}
/**
* 提供默认服务
* @return
*/
public static Service newInstance(){
return newInstance(DEFAULT_PROVIDER);
}
/**
* 根据相应条件提供特定服务
* @param name
* @return
*/
public static Service newInstance(String name){
Provider provider = providers.get(name);
if(provider == null)
throw new IllegalArgumentException("服务不存在");
return provider.newService();
}
/**
* 服务提供者接口
*/
interface Provider{
/**
* 实例化一个服务
* @return
*/
Service newService();
/**
* 注册提供者
*/
void registProvider();
}
/**
* 服务接口
*/
interface Service{
default void say(){
System.out.println("i am default");
}
}
}
/**
* 服务A
*/
public class ServiceA implements Services.Service{
public void say(){
System.out.println("i am A");
}
/**
* 服务提供者,负责注册服务,构建服务类
*/
static class ProviderA implements Services.Provider{
public final static String NAME = "A";
@Override
public Services.Service newService() {
return new ServiceA();
}
@Override
public void registProvider() {
Services.registProvider(NAME,this);
}
}
}
/**
* 服务B
*/
public class ServiceB implements Services.Service{
public void say(){
System.out.println("i am B");
}
/**
* 服务提供者,负责构建服务 向Services类注册服务
*/
static class ProviderB implements Services.Provider{
public final static String NAME = "B";
@Override
public Services.Service newService() {
return new ServiceB();
}
@Override
public void registProvider() {
Services.registProvider(NAME,this);
}
}
}
一个测试例子
public class Client {
public static void main(String[] args){
Services.Provider providerA = new ServiceA.ProviderA();
Services.Provider providerB = new ServiceB.ProviderB();
providerA.registProvider();
providerB.registProvider();
Services.Service service = Services.newInstance("B");
service.say();
}
}
最终打印
i am B
2、遇到多个构造器参数时要考虑用构建器
重叠构造器模式可行,但是当有许多参数的时候,客户端代码会很难编写,过多的构造器也不利于阅读
使用构建器,优点
1、客户端代码更加清晰,利于阅读
2、可以在set方法或者build中对传入参数进行验证,及时抛出异常
一个简单的例子
/**
* 不可变类,构造器私有
*/
public class Service {
private final String name;
private final int age;
private final int height;
private final int weight;
/**
* 内部构建器,通过构建器实例化类
*/
public static class Bulider{
private final String name;
private int age;
private int height;
private int weight;
public Bulider(String name){
this.name = name;
}
public Bulider setAge(int age){
this.age = age;
return this;
}
public Bulider setHeight(int height){
this.height = height;
return this;
}
public Bulider setWeight(int weight){
this.weight = weight;
return this;
}
public Service bulider(){
return new Service(this);
}
}
public String toString(){
return "name:"+name+" age:"+age+" height:"+height+" weight:"+weight;
}
private Service(Bulider bulider){
this.name = bulider.name;
this.age = bulider.age;
this.height = bulider.height;
this.weight = bulider.weight;
}
public static void main(String[] args){
Service service = new Bulider("张三")
.setAge(10).setHeight(170).setWeight(120).bulider();
System.out.println(service.toString());
}
}