什么时候使用静态工厂方法?

通过静态工厂方法替代构造器

Posted by MasterJen on November 19, 2018

Hey static factory

Do one thing at a time, and do well.–一次只做一件事,做到最好!

最近在看一本必修书籍Effective java ,收获颇丰,里面有个静态工厂的使用,今天就总结一下吧.

对于类而言,为了让客户端获取它自身的一个实例,最常用的方法就是提供一个公有的构造器.还有一种方法,就是提供一个公有的静态的工厂方法,它只是返回类的实例的静态方法.

那么使用静态方法有什么优势呢?

第一 它们有名称,产生的客户端代码也更易于阅读.
第二 不必在每一次创建对象时都创建一个新的对象.
第三 它们可以返回原返回数据的任何子类型的对象.
第四 在创建参数化类型实例时,使代码变的更加简单.

当然 它也有着一些缺点,比如:类如果不含公有的或者受保护的构造器,就不能被子类化.

测试案例如下 : 需求就是返回一个Service接口

Service接口:

public interface Service {
}

提供者Service接口的接口 ,Provider

public interface Provider {
    Service newService();
}

Provider实现类

public class ProviderExtends implements Provider {
    @Override
    public Service newService() {
        System.out.println("获得了Service");
        return null;
    }
}

具体实现类: Services

public class Services {
//    提供构造方法
    private Services(){};
//    创建 map集合 用于存放 Provider String 是 Provider的名字,Provider是提供者  ConcurrentHashMap 是线程安全的map
    private static final Map<String,Provider> providers = new ConcurrentHashMap<String,Provider>();
//  起一个默认的名字  就是 test
    public static final String DEFAULT_NAME = "test";
//  注册一个 Provider 名字是test
    public static void registerDefaultProvider(Provider provider){
        registerProvider(DEFAULT_NAME,provider);
    }
//    注册 Provider 放到 map中
    private static void registerProvider(String defaultName, Provider provider) {
        providers.put(defaultName,provider);
    }
//    返回需求  得到 Service  通过默认的Provider类
    public static Service newInstance(){
        return newInstance(DEFAULT_NAME);
    }
//    获得 Service 首先从map里面获取 该默认的Provider 类
    public static Service newInstance(String name){
        Provider provider = providers.get(name);
        if(provider==null){
            throw new IllegalArgumentException("No provider register with name : "+name);
        }
        return provider.newService();
    }
      public static void main(String[] args) {
//        首先进行注册 Provider
        ProviderExtends providerExtends = new ProviderExtends();
        Services.registerDefaultProvider(providerExtends);
          Service service = Services.newInstance();
      }
}

这样就完成了通过静态工厂获取实例对象,替代了构造器.