工厂方法和私有变量

时间:2011-12-09 00:36:35

标签: php oop design-patterns factory

我正在使用工厂类来创建另一个类的实例,比如Product类。

如何在工厂类中设置Product类中的私有变量?我应该这样做吗?

我打算做的是公共setter方法,然后在完成后冻结或锁定实例。但我觉得这是做错事的错误方法。

你会如何解决这个问题?

编辑:

是的我想使用@derekerdmann的不可变对象方法。但我可能应该首先提供更多信息。

我正在用php编写一个类似HTML语言的解析器,因此您可以获得节点,而节点又可以包含其他节点。因此工厂是一个生成节点层次结构的解析器。如果您对此感到好奇,请输入代码http://http://bazaar.launchpad.net/~rhlee/band-parser/dev/view/head:/src/bands.php

问题是,在我走下文档的其余部分之前,我不知道子节点是什么。所以我无法传递给构造函数。

有时我认为即使我想要它只能在解析后才能读取,为什么它应该是?我以php的DOMDocument解析器为例。您可以解析HTML文件,然后仍然可以修改结构。但是,这样您可以使用新更改再次重现HTML。我的解析器是一个单向解析器,因此在解析后编辑结构的需要是不存在的。

3 个答案:

答案 0 :(得分:3)

执行此操作的典型方法是创建不可变对象。在不可变对象中,通过将值传递到对象的构造函数来设置所有私有字段。不可变= =不可修改。

如果确实需要一种方法来更改私有字段,则setter方法实际上会创建一个包含已更改字段的新实例。

示例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 );
    }

}

答案 1 :(得分:0)

我认为在工厂的情况下,@ 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;
  }
}

答案 2 :(得分:0)

更优雅的方法是使用package-private构造函数和setter。

在Java中的示例中,创建一个包“x.y.z”并将两个类放在那里。

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;
    }
}

你可以read more about member/method access control here