Фабричные методы и приватные переменные - PullRequest
5 голосов
/ 09 декабря 2011

Я использую фабричный класс для создания экземпляров другого класса, скажем, класса Product.

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

Что я планирую сделать, так это использовать методы открытого сеттера, а затем заморозить или заблокировать экземпляр, как только я закончу с ним.Но я чувствую, что это неправильный способ делать вещи.

Как бы вы подошли к такой проблеме?

РЕДАКТИРОВАТЬ:

Да, я хотел бы использовать @ derekerdmann'sметод неизменяемых объектов.Но я, вероятно, сначала должен дать больше информации.

Я пишу парсер на php для HTML-подобного языка, чтобы вы получили узлы, которые, в свою очередь, могут содержать другие узлы.Таким образом, фабрика является синтаксическим анализатором, создающим иерархию узлов.Если вам интересно, вот код http://http://bazaar.launchpad.net/~rhlee/band-parser/dev/view/head:/src/bands.php

Дело в том, что я не знаю, какими будут дочерние узлы, пока не пройдусь по остальной части документа.Поэтому я не могу перейти к конструктору.

Иногда я думаю, что, хотя я хочу , чтобы он читался только после разбора, почему это должно быть?Я беру например парсер DOMDocument от php.Вы можете проанализировать HTML-файл, а затем все еще изменить структуру.Однако это так, что вы можете снова воспроизвести HTML с новыми изменениями.Мой синтаксический анализатор является односторонним анализатором, поэтому необходимость в редактировании структуры после синтаксического анализа отсутствует.

Ответы [ 3 ]

3 голосов
/ 09 декабря 2011

Типичный способ сделать это - создать неизменных объектов .В неизменяемом объекте все приватные поля устанавливаются путем передачи значений в конструктор объекта.Неизменяемый == неизменяемый.

Если вам нужен способ изменить закрытые поля, методы установщика фактически создадут новый экземпляр с измененными полями.

Пример класса Java:

class ImmutableDuck {

    private final String name;
    private final int age;

    /**
     * Constructor - sets the read-only attributes of the duck
     */
    public ImmutableDuck( String name, int age ){
        this.name = name;
        this.age = age;
    }

    public String getName(){
        return name;
    }

    public int getAge(){
        return age;
    }

    /**
     * Creates a new ImmutableDuck with the current object's age 
     * and the given age
     */
    public ImmutableDuck setName( String name ){
        return new ImmutableDuck( name, age );
    }

}
0 голосов
/ 18 декабря 2011

Несколько более элегантный способ - использовать конструкторы и сеттеры, работающие с пакетами.

Пример на Java, создайте пакет "x.y.z" и включите оба класса.

* * 1004 Thing.java
package x.y.z;

public class Thing {

    private int something;

    Thing(final int something) {
        this.something = something;
    }

    void setSomething(final int something) {
        this.something = something;
    }

    public int getSomething() {
        return something;
    }
}

ThingFactory.java:

package x.y.z;

public class ThingFactory {

    public static Thing createThing() {
        Thing thing = new Thing(1337);
        thing.setSomething(9001);
        return thing;
    }
}

Вы можете узнать больше об управлении доступом к элементу / методу здесь .

0 голосов
/ 09 декабря 2011

Я думаю, что в заводской ситуации решение, предложенное @derekerdmann, является правильным. Однако, один из способов выполнить то, о чем просит @rhlee, - это создать «заблокированный» класс, для разблокировки которого требуется key. Пример PHP:

class Thing {
  private $key = '';
  private $name = '';

  public function __construct($key) {
    $this->key = $key;
  }

  public function setName($key, $name) {
    $unlocked = ($this->key == $key);
    if ($unlocked) $this->name = $name;
    return $unlocked;
  }
}
...