Effective Java 读书笔记

第二章  创建与销毁对象

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());
    }

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值