工厂模式。 何时使用工厂方法?

什么时候在对象内使用工厂方法而不是Factory类是一个好主意?


我喜欢根据我的课程是“人”来思考设计模式,模式是人们彼此交谈的方式。

所以,对我来说,工厂模式就像一个招聘机构。 你有人需要可变数量的工人。 这个人可能知道他们雇用的人需要的信息,但就是这样。

所以,当他们需要一名新员工时,他们会打电话给招聘机构,告诉他们他们需要什么。 现在,要真正聘请某人,您需要了解很多东西 - 福利,资格验证等。但招聘人员并不需要知道这些 - 招聘机构处理所有这些。

同样,使用Factory可以让消费者创建新的对象,而不必知道他们如何创建的细节,或者他们的依赖关系 - 他们只需要提供他们实际需要的信息。

public interface IThingFactory
{
    Thing GetThing(string theString);
}

public class ThingFactory : IThingFactory
{
    public Thing GetThing(string theString)
    {
        return new Thing(theString, firstDependency, secondDependency);
    }
}

所以,现在ThingFactory的使用者可以得到Thing,而不必知道Thing的依赖关系,除了来自消费者的字符串数据。


工厂方法应该被视为构造函数的一种替代方法 - 主要是当构造函数没有足够的表达能力时,即。

class Foo{
  public Foo(bool withBar);
}

并不像以下那样具有表现力:

class Foo{
  public static Foo withBar();
  public static Foo withoutBar();
}

当你需要一个复杂的过程来构造对象时,当构造需要一个你不需要的实际类的依赖时,当你需要构造不同的对象时,工厂类很有用。


我个人发现独立工厂类的一种情况是,当你尝试创建的最终对象依赖于其他几个对象时。 例如,在PHP中:假设你有一个House对象,而House对象又有一个Kitchen和一个LivingRoom对象,而LivingRoom对象也有一个TV对象。

最简单的方法是让每个对象在他们的构造方法上创建他们的子项,但是如果这些属性是相对嵌套的,那么当你的House失败创建时,你可能会花一些时间试图确切地分离失败的东西。

另一种方法是执行以下操作(依赖注入,如果你喜欢这个奇特的术语):

$TVObj = new TV($param1, $param2, $param3);
$LivingroomObj = new LivingRoom($TVObj, $param1, $param2);
$KitchenroomObj = new Kitchen($param1, $param2);
$HouseObj = new House($LivingroomObj, $KitchenroomObj);

在这里,如果创建House的过程失败了,那么只有一个地方可以看,但是每次想要一个新House都不得不使用这个House 。 输入工厂:

class HouseFactory {
    public function create() {
        $TVObj = new TV($param1, $param2, $param3);
        $LivingroomObj = new LivingRoom($TVObj, $param1, $param2);
        $KitchenroomObj = new Kitchen($param1, $param2);
        $HouseObj = new House($LivingroomObj, $KitchenroomObj);

        return $HouseObj;
    }
}

$houseFactory = new HouseFactory();
$HouseObj = $houseFactory->create();

由于这里的工厂,创建House的过程被抽象出来(因为当你只想创建一个House时,你不需要创建和设置每一个依赖项),同时集中化使得更容易维护。 为什么使用单独的工厂还有其他一些原因可能是有益的(例如可测试性),但我发现这个特定的用例可以很好地说明工厂类如何有用。

链接地址: http://www.djcxy.com/p/77841.html

上一篇: Factory Pattern. When to use factory methods?

下一篇: How can I determine if an angular factory/service has been previously injected