一、考虑用静态工厂的方法代替构造器
类通过提供一个一个公有的静态工厂方法来返回类的实例。
静态工厂方法与构造器不同的第一个优势在与,静态工厂方法是有名字的。而对于构造器而,同一类中的构造器都据有一个完全一样的名字,阅读性差。
静态工厂方法与构造器不同的第二大优势在于,不必在每次调用他们的时候都创建一个对象。静态工厂方法能够为重复的调用返回相同的对象,这样有助于类总能控制在某个时刻哪些实例应该存在。
由于java面向对象的多态特性,静态工厂方法与构造器不同的的第三大优势在于他们可以返回原返回类型的任何子类型对象。
静态工厂方法的第四大优势在于,在创建参数化类型实例的时候,他们使代码变得简介。下面是一个使用静态工厂方法的实例:
服务接口:
public interface Service {
}
提供者接口:
package unit_1.stafactory;
public interface Provider {
Service newService();
}
运用静态工厂方法实例化:
package unit_1.stafactory;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Services implements Service{
private Services(){}
private static final Map<String,Provider> provider=new ConcurrentHashMap<String,Provider>();
public static final String DEFAULT_PROVIDER_NAME="<def>";
//提供者注册的方法
public static void registerProvider(String name,Provider p)
{
registerProvider(DEFAULT_PROVIDER_NAME,p);
}
public static void registerDefaultProvider(String name,Provider p)
{
provider.put(name, p);
}
//服务范文方法
public static Service newInstance()
{
return newInstance(DEFAULT_PROVIDER_NAME);
}
public static Service newInstance(String name)
{
Provider p=provider.get(name);
return p.newService();
}
}
二、遇到多个参数时要考虑用构建器
静态工厂和构造器有个共同的局限性:他们都不能很好地扩展到大量的可选参数。通常我们会使用重叠构造器模式,在这种模式下,第一个构造器提供包含所有必要参数的构造器,第二个构造器包含一个可选参数,第三个包含两个可选参数,依次类推,最后一个包含所有的可选参数。但是这种方法可读性差。
当然还有另一种办法,即用JavaBeans模式,通过调用一个无参函数来构造对象,其他的域都通过set方法来实现。这种方法存在一个问题,就是存在线程安全的问题。
这时候,构建器就成为一种很好的替代方法了。实例如下所示:
package unit1.builder;
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder
{
private final int servingSize;
private final int servings;
private int calories=0;
private int fat=0;
private int carbohydrate=0;
private int sodium=0;
public Builder(int servingSize,int servings)
{
this.servingSize=servingSize;
this.servings=servings;
}
public Builder calories(int val)
{
calories=val;
return this;
}
public Builder fat(int val)
{
fat=val;
return this;
}
public Builder sodium(int val)
{
sodium=val;
return this;
}
public Builder carbohydrate(int val)
{
carbohydrate=val;
return this;
}
public NutritionFacts build()
{
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder)
{
servingSize=builder.servingSize;
servings=builder.servings;
calories=builder.calories;
fat=builder.fat;
sodium=builder.sodium;
carbohydrate=builder.carbohydrate;
}
}