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


当前回答

任何将对象创建延迟到其需要使用的对象的子类的类都可以视为Factory模式的示例。

我在https://stackoverflow.com/a/49110001/504133的另一个回答中详细提到过

其他回答

当您需要几个具有相同参数类型但具有不同行为的“构造函数”时,它们也很有用。

这真的是个品味问题。工厂类可以根据需要进行抽象/接口,而工厂方法是轻量级的(而且往往是可测试的,因为它们没有定义的类型,但它们需要一个众所周知的注册点,类似于服务定位器,但用于定位工厂方法)。

我简短的解释是,当我们没有足够的信息来创建一个具体的对象时,我们使用工厂模式。我们要么不知道依赖关系,要么不知道对象的类型。我们几乎总是不知道它们因为这是运行时的信息。

示例:我们知道我们必须创建一个车辆对象,但我们不知道它是飞行还是在地面上工作。

当它们返回的对象类型具有私有构造函数时,当不同的工厂类在返回的对象上设置不同的属性时,或者当特定的工厂类型与其返回的具体类型耦合时,工厂类非常有用。

WCF使用ServiceHostFactory类来检索不同情况下的ServiceHost对象。IIS使用标准的ServiceHostFactory来检索.svc文件的ServiceHost实例,但是WebScriptServiceHostFactory用于向JavaScript客户端返回序列化的服务。ADO。NET Data Services有自己特殊的DataServiceHostFactory和ASP。NET有它的ApplicationServicesHostFactory,因为它的服务有私有构造函数。

如果只有一个类在使用工厂,那么可以在该类中使用工厂方法。

我个人认为单独的Factory类有意义的一种情况是,当您试图创建的最终对象依赖于其他几个对象时。例如,在PHP中:假设你有一个House对象,它又有一个Kitchen和一个LivingRoom对象,LivingRoom对象内部也有一个TV对象。

实现这一点的最简单方法是让每个对象在它们的construct方法上创建它们的子对象,但是如果属性是相对嵌套的,那么当您的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时都必须使用这个块,这非常不方便。进入工厂:

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时,您不需要创建和设置每个依赖项),同时是集中的,这使得它更容易维护。使用单独的工厂是有益的还有其他原因(例如可测试性),但我发现这个特定的用例最好地说明了工厂类是如何有用的。