gpt4 book ai didi

PHP:松耦合参数化工厂。是否可以?

转载 作者:行者123 更新时间:2023-12-04 10:53:15 25 4
gpt4 key购买 nike

我的需求:
我想实例化一个对象,其中新对象的类由作为工厂方法参数给出的对象确定。同时,我希望工厂方法保持松散耦合,以便在添加新产品类时不需要更新。看起来像下面的代码这样的参数化工厂是一个解决方案,但与产品类紧密耦合。

我在做什么:
我在以不同格式保存基本相同信息的数据对象之间进行翻译。这些需要从一种格式转换为另一种格式,但在它们请求翻译器之前,我不知道数据对象属于哪个类。我知道翻译器是如何实现的,但我正在努力解决如何为给定的对象选择合适的翻译器,而无需进行大量检查对象所属的类。我想我应该使用工厂根据数据对象是instanceof的类来返回兼容的翻译器。

“有效”但紧密耦合的通用代码:

class Factory {

public static function getTranslator( object $a, object $b ): Product {
if( ( $a instanceof ClassOne && $b instanceof ClassTwo )
|| ( $a instanceof ClassTwo && $b instanceof ClassOne )
) {
return new TranslatorForClassOneAndTwo( $a, $b );
}
if( ( $a instanceof ClassOne && $b instanceof ClassThree )
|| ( $a instanceof ClassThree && $b instanceof ClassOne ) ) {
return new TranslatorForClassOneAndThree( $a, $b );
}
if( ( $a instanceof ClassTwo && $b instanceof ClassThree )
|| ( $a instanceof ClassThree && $b instanceof ClassTwo ) ) {
return new TranslatorForClassTwoAndThree( $a, $b );
}
//...and so on.
}
}

用法:
    $object_a = new CrmData();
$object_b = new CmsData();
$object_c = new MarketingData();

//Translate object_a to object_b
$translator_alpha = Factory::getTranslator($object_a , $object_b);
$translated_object_one = $translator_alpha->translate($object_a , $object_b);

$translator_beta = Factory::getTranslator($object_a , $object_c);
$translated_object_two = $translator_beta->translate($object_a , $object_c);

//$translated_object_one is the data of $object_a but same class as $object_b, CmsData
//$translated_object_two is the data of $object_a but same class as $object_c, MarketingData

使用上面的代码,每次我添加一个新的 Product 时,我都需要向这个工厂方法添加一个新的案例。类(class)。如果有一种方法可以基于与上述相同的逻辑实例化这些产品,而无需明确定义每个案例,那将是更可取的。似乎有一种方法可以使用一些面向对象的结构来做到这一点,但我没有想法。此外,了解这在 php 中目前是否不可能,如果没有好的解决方案,我会坚持使用更明确的结构,这将很有帮助。

最佳答案

另一种可能性(与我的其他答案不同,更接近您自己的答案):

  • Translator对象响应 canTranslateBetween(Translatable, Translatable): bool (这可以在契约(Contract)上定义为 PHP 中的抽象静态方法,顺便说一句),
  • Factory将一组翻译器类作为依赖项(构造函数参数),然后实例化其中正确的一个。

  • 你的工厂类看起来像这样:
    class TranslatorFactory
    {
    /** @var string[] */
    private $translatorClasses;

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

    public function createTranslator(Translatable $a, Translatable $b): Translator
    {
    foreach ($this->translatorClasses as $translatorClass) {
    if ($translatorClass::canTranslateBetween($a, $b)) {
    return new $translatorClass;
    }
    }
    throw new \RuntimeException('Could not find translator.');
    }
    }

    用法:
    $translatorFactory = new TranslatorFactory([
    Translator1::class,
    Translator2::class,
    Translator3::class
    ]);

    $translatable1 = new Translatable1();
    $translatable3 = new Translatable3();
    $translator = $translatorFactory->createTranslator($translatable1, $translatable3);

    这具有以任何方式干净且非黑客的优点(没有“魔法”或反射或任何类似的东西)。唯一的缺点是,必须在实例化工厂时手动列出所有翻译类,但我觉得这实际上是有道理的:毕竟,它会从中选择一个。

    演示:https://3v4l.org/nfuB2

    关于PHP:松耦合参数化工厂。是否可以?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59362609/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com