Java 编程--代码的选择

本文探讨了Java编程中使用静态工厂方法替代构造器的优势,如命名描述对象、灵活的实例化策略。同时,提到了构建器在处理多个参数时的作用,以及单例模式下私有构造器或枚举的应用。此外,还讨论了避免不必要的对象创建和公有类的成员访问控制问题。
摘要由CSDN通过智能技术生成

Java 编程–代码的选择

以下几点Java编程建议都是取自Effective Java的.所以本篇也算是Effective Java的读书笔记了。

使用静态工厂方法替代构造器

public class Product {
    private static Product computer;

    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public Product(String name) {
        this.name = name;
    }

    public static Product getComputer(){
        return new Product("Computer");
    }

    public static Product getStaticComputer() {
        if (this.computer == null) {
            this.computer = new Product("computer");
        }
        return this.computer;
    }
}

public class Container {
    public static void main(String[] args) {
        // 1.通过构造器创建“computer”对象
        Product computer1 = new Product("computer");
        // 2.通过静态工厂方法创建“computer”对象
        Product computer2 = Product.getComputer();
    }
}

好处:
- 静态工厂方法有名称来描述需要创建什么样的对象
- 静态工厂可以觉得是否每次都创建新的对象(代码中getStaticComputer()方法演示了这种情况)
- 静态方法里可以返回原类型的任何子类型对象
缺点:
- 如果类没有共有的构造器, 就无法继承
- 静态工厂方法其实与静态方法没有任何区别

构造器与构建器

public class Product {
    private String name;

    private float weight;

    public Product(String name, float weight) {
        this.name = name;
        this.weight = weight;
    }

    public Product(String name) {
        this.name = name;
    }

    public Product(float weight) {
        this.weight = weight;
    }

    private Product(Builder builder) {
        setName(builder.name);
        setWeight(builder.weight);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getWeight() {
        return weight;
    }

    public void setWeight(float weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                ", weight=" + weight +
                '}';
    }
    /**
     * 构建器
     */
    public static final class Builder {
        private String name;
        private float weight;

        public Builder() {
        }

        public Builder name(String val) {
            name = val;
            return this;
        }

        public Builder weight(float val) {
            weight = val;
            return this;
        }

        public Product build() {
            return new Product(this);
        }
    }
}

使用构建器的好处是,在有多个参数情况下,如果使用构造器的话就需要多个构造器,而且排列组合很可能产生参数组合爆炸。构建器很容易实例化参数多的情况。但是使用构建器是需要在实例化对象之前实例化构建器对象。所以,这个构建器消耗资源比构造器大。

使用私有构造器或者枚举来强化单例

public class Product {
    private static Product instance;
    // 私有化构造器,外部只能通过静态工厂方法来实例化单例;
    private Product() {
    }

    public Product getInstance() {
        if (instance != null) {
            instance = new Product();
        }
        return instance;
    }
}

如果不能实例化的类,通过构造器来实现

public class Factory {
    private Factory() {
        throw new Exception("Factory 不能够被实例化");
    }
    // 下面这段代码将会报错
    public Product getInstance() {
        return new Factory();
    }
}

避免创建不必要的对象

String s = new String("hello world");// String s = "hello world";
public class Person {
    private final Date birthDate;

    public boolean isBabyBoomer() {
        Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
        Date boomStart = gmtCal.getTime();
        gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
        Date boomEnd = gmtCal.getTime();
        return birthDate.compareTo(boomStart) >= 0 && birthDate.compareTo(boomEnd) < 0;
    }
}

// 下面的实现方式比上面这种好,因为它避免了对象的重复创建
public class Person {
    private final Date birthDate;

    private static final Date = BOOM_START;
    private static final Date = BOOM_END;

    static {
        Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
        gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);
        Date boomStart = gmtCal.getTime();
        gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);
        Date boomEnd = gmtCal.getTime();
        BOOM_START = boomStart;
        BOOM_END = boomEnd;
    }

    public boolean isBabyBoomer() {
        return birthDate.compareTo(boomStart) >= 0 && birthDate.compareTo(boomEnd) < 0;
    }
}

公有类是否暴露公有域

通俗一点,这个问题可以说: JavaBean字段是否用public声明

// 实现一
pubic class Point {
    public double x;
    public double y;
}

// 实现二
pubic class Point {
    private double x;
    private double y;

    public double getX() { return x; }  
    public double getY() { return y; }

    public void setX(double x) { this.x = x; }
    public void setY(double y) { this.y = y; }
}

以上两种实现让你来评价你选择哪种?

实现一优势:

  • 实现简单
  • 封装数据结构

实现二优势:

  • 封装逻辑
  • 不暴露对数据的操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值