从'getter'方法返回值的最佳应用



'将类字段/属性设为私有' - 是 OOP 中的最佳实践之一。要访问private字段/属性,我们可以使用公共 getter 方法。但是根据这个博客,仅仅编写getter方法可能还不够(请参阅引用2)。它建议从 getter 方法返回字段/属性的克隆(如果是引用类型)。通过遵循这种方法,我们可以使字段/属性不可修改。请参阅下面的代码 -

public class Department{  
 Employee admin;  
 ...  
 ...  
 ...  
 public Employee getAdmin(){  
   return admin.clone();
 }  
}

因此,从现在开始,如果我们不使用任何二传手'admin'就无法被外部世界修改。这种方法看起来很不错。但我几乎没有找到任何实现这种方法的代码。使用这种方法是否有任何缺点,可能会破坏使用这种方法的好处?
提前谢谢。

这种方法的主要缺点是每次获得对象时都需要制作克隆,这并不理想,因为理想情况下,您更喜欢轻量级的 getter。

有两种方法可以在不克隆的情况下实现类似的效果:

  • 使Employee不可变,并且
  • Employee提供不可变的接口

第一种方法是不言自明的,并且非常有效,但它并不总是实用的,尤其是在对象表示需要就地共享的状态的情况下。

第二种方法也很简单:与其Employee成为一个类,不如让它成为一个只有getter的接口,创建一个实现Employee的类EmployeeImpl,并具有getter和setter,并在需要可变性时使用类。

public interface Employee {
    String getFirstName();
    String getLastName();
}
public class EmployeeImpl implements Employee {
    private String firstName;
    private String lastName;
    public String getFirstName() {return firstName;}
    public String getLastName() {return lastName;}
    public void setFirstName(String name) {firstName = name;}
    public void setLastName(String name) {lastName = name;}
}

这种方法可以通过投射到一个类来击败,但大多数时候它是可以的。

如果您处于敌对环境中,对实际对象的任何修改都将非常有害 - 例如,您正在为您的服务公开一些每个人都可以下载和使用的 API,您将不得不采用您描述的完整克隆方法。但是,这种情况相对较少。

注意:自从它首次发布以来,我更改了此答案。我建议的第一个解决方案存在继承问题,现在已经解决了。

克隆返回的对象通常是一个非常糟糕的选择。除非对象非常简单,或者您的应用程序不是很复杂,否则所有这些克隆很可能会带来巨大的开销。

针对特定情况的另一种方法是使用一个名为 Employee 的接口,该接口仅提供 getter。然后,还可以定义实现Employee并提供资源库的 MutableEmployee 类。

interface Employee {
    public String getName();
    public float getSalary();
}
class MutableEmployee implements Employee {
    private String name;
    private float salary;
    @Override
    public String getName() {
        return name;
    } 
    @Override
    public float getSalary() {
        return salary;
    }
    public void setSalary(float salary) {
        super.salary = salary;
    }
    public void setName(String name) {
        super.name = name;
    }
}

然后,您的Department类将像这样修改:

class Department {
    private MutableEmployee admin;
    public Employee getAdmin() {
        return (Employee) admin;
    }
    public MutableEmployee getMutableAdmin() {
        return admin;
    }
}

定义MutableEmployee的子类

当你想创建一个MutableEmployee的子类时,比如MutableGraphicDesigner,你需要定义以下内容:

  1. interface GraphicDesigner extends Employee
  2. class MutableGraphicDesigner extends MutableEmployee implements GraphicDesigner

最新更新