Сокрытие мутаторов, требуется разъяснение - PullRequest
1 голос
/ 21 сентября 2011

Предположим, у вас есть класс Dog, который имеет

public class Dog {

    private String name;
    private double age;

    // some setters
    // some getters

Кроме того, у вас есть класс DogHandler, который создает экземпляр Dog d и передает его Owner

Полагаю, я могу

... сделайте копию собаки, прежде чем передать ее на Owner, но это дорогостоящая операция, и я бы предпочел ее избежать.

... придумайте интерфейс, который реализует Dog, который содержит только геттеры, приведите Dog к этому интерфейсу и передайте результат по

... инициализировать устанавливаемые переменные в конструкторе и просто не разрешать изменения для этого экземпляра объекта

Есть ли другие способы убедиться, что получатель объекта не может изменить его?

Как взять простой бин, содержащий некоторые данные, и сделать его доступным только для чтения?

Ответы [ 4 ]

2 голосов
/ 22 сентября 2011

Это может быть достигнуто несколькими способами, я могу предложить вам 2 из них:

а) интерфейс с геттерами - хорошая идея

б) создать производный класс от Dog с методом settersзаблокирован, как это:

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());
0 голосов
/ 22 сентября 2011

Вот пример использования интерфейса и установщиков доступа к пакетам.


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");
    }
  }
0 голосов
/ 22 сентября 2011

Среди решений, упомянутых здесь, вы также можете воспользоваться модификаторами видимости. Если Dog и Owner находятся в отдельных пакетах, вы можете установить видимость мутаторов для области по умолчанию (пакета) или защищенной области.

Это позволит вам сохранить Dog и DogHandler в одном и том же пакете (и, следовательно, позволить им обоим мутировать объект Dog соответственно), сохраняя при этом отдельные объекты Owner (и, следовательно, предотвращая их любая модификация Dog объектов).

0 голосов
/ 22 сентября 2011

Подходы, которые вы упоминаете в этом вопросе, в значительной степени являются стандартными шагами, чтобы сделать Dog неизменным. Единственный другой совет - предписать, что Dog нельзя переопределить, объявив класс final.

.
...