一天一条EffectiveJava:考虑用静态工厂方法代替构造器

此处的静态工厂方法有别于设计模式中的工厂模式:泛指能够返回类的一个实例的静态方法。例如Boolean的valueOf方法:

 /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code true}.
     */
    public static final Boolean TRUE = new Boolean(true);

    /**
     * The {@code Boolean} object corresponding to the primitive
     * value {@code false}.
     */
    public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }

使用静态工厂方法代替构造器的好处有:
1、方法有名称:通过正确命名可以更确切地描述返回的实例对象,使代码更易阅读。
2、不会在每次调用时都创建新对象。静态工厂方法会预先构建好对象或缓存对象,已达到重复利用对象的目的,避免过多地创建不必要的对象。在频繁请求创建同一个对象的情况下,能一定程度地提升性能。
3、可以返回原返回类的任意子类的对象。
服务者提供框架例子:

//服务提供者接口,用来提供服务
//这个接口时可选的,如果没有,下面的Map集合就可以直接存放Service对象
public interface Provider {
    Service newService();
}

//服务接口, 用来写具体的服务内容
public interface Service {
  // Service-specific methods go here
}

public class Services {
	 private Services() {
	    } // Prevents instantiation (Item 4)

	    // Maps service names to services
	    //服务的注册和访问
	    //用一个Map来存放提供这的名字和提供者的对象
	    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);
	    }
	    //所谓注册就是在加入Map
	    public static void registerProvider(String name, Provider p) {
	        providers.put(name, p);
	    }
	    
	 // Service access API
	    //使用这个方法创建实例
	    public static Service newInstance() {
	        return newInstance(DEFAULT_PROVIDER_NAME);
	    }

	    //创建的时候看缓存里有没有provider
	    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();
	    }

}

测试:

public class TestNo1 {
	public static void main(String[] args) {
        //测试的时候先注册,然后在再创建相应地对象,这里的provider使用内部类
        //由provider返回具体的service实例
        // 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的toString方法
        Service s1 = Services.newInstance();
        Service s2 = Services.newInstance("comp");
        Service s3 = Services.newInstance("armed");
        System.out.printf("%s, %s, %s", s1, s2, s3);
        
    }
	//Provider的匿名内部类
    private static Provider DEFAULT_PROVIDER = new Provider() {
        public Service newService() {
        	//Service的匿名内部类
            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";
                }
            };
        }
    };
}

4、在创建参数化类型实例时,能使代码更简洁。
以上为使用静态工厂方法创建实例的优势。看着跟策略模式很像哈。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值