隐藏变异者,需要澄清

时间:2011-09-21 19:39:03

标签: java design-patterns encapsulation data-hiding

假设您有一个类Dog,它有

public class Dog {

    private String name;
    private double age;

    // some setters
    // some getters

此外,您有一个班级DogHandler,它会生成Dog d的一个实例并将其传递给Owner

我想,我可以

...在将狗传递给Owner之前制作一份狗的副本,但这是一项昂贵的操作,我宁愿避免使用它。

...提出Dog实现的接口,其中仅包含getter,将Dog强制转换为该接口并传递结果

...在构造函数中初始化可设置变量,并且根本不允许更改此对象实例

还有其他方法可以确保对象的接收者无法修改它吗?

如何获取包含某些数据的简单bean并将其设为只读?

4 个答案:

答案 0 :(得分:2)

这可以通过几种方式实现,我可以向你提出其中两种:

a)与getter的接口是个好主意

b)从Dog创建派生类,其中setter方法被阻止,如下所示:

class UnmodifiedDog extends Dog {
    public UnmodifiedDog(double age, String name) {
        super.setAge(age);
        super.setName(name);
    }
    @Override
    public void setAge(double age) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void setName(String name) {
         throw new UnsupportedOperationException();
    }   
}

在DogHandler:

Dog createDog() {
    return new UnmodifiedDog(10, "Fido");
}

您可以将此传递给所有者:

owner.receiveDog(dogHandler.createDog());

答案 1 :(得分:0)

您在问题中提到的方法几乎是使Dog不可变的标准步骤。唯一的另一个提示是强制要求Dog无法通过将类声明为final来覆盖。

答案 2 :(得分:0)

在此处提到的解决方案中,您还可以利用可见性修饰符。如果DogOwner位于不同的包中,则可以将mutator的可见性设置为默认(包)范围或受保护的范围。

这将允许您将DogDogHandler保留在同一个包中(因此允许它们相应地改变Dog对象),同时保留Owner个对象分开(因此阻止他们对Dog个对象进行任何修改。)

答案 3 :(得分:0)

以下是使用接口和包访问设置器的示例。


package blah.animal;
public interface Dog
{
  double getAge();
  String getName();
}

package blah.animal;
public class DogImpl implements Dog
{
  private double age; // double seems wrong for age.
  private String name;

  ... getters (defined by Dog interface)

  // package access setters.
  void setAge(double newValue)
  {
    age = newValue;
  }

  void setName(String newValue)
  {
    name = newValue;
  }

  package blah.animal;
  public class DogHandler
  {
    public static Dog newDog(double age, String name)
    {
      Dog returnValue = new DogImpl();
      returnValue.setAge(age);
      returnValue.setName(name);

      return returnValue;
    }
  }

  package.blah.somethingelse;
  public class Blam
  {
    private Dog myDog;

    public Blam()
    {
      myDog = DogHandler.newDog(1.4D, "Tippy");
    }
  }