首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP -一个工厂的产品有特殊的方法

PHP -一个工厂的产品有特殊的方法
EN

Stack Overflow用户
提问于 2018-04-10 06:12:44
回答 3查看 60关注 0票数 0

我试着用工厂模式来创造产品。我为产品类创建了一个接口来实现和设计一个工厂,该工厂将根据传递给它的参数生成产品。

接口

代码语言:javascript
复制
interface Product
{
  public function getName();
}

产品

代码语言:javascript
复制
class ProductA implements Product{
  public function getName()
  {
    return 'A'; 
  }
}

class ProductB implements Product{
  public function getName()
  {
    return 'B'; 
  }
  public function SpecialMethod()
  {
    return 'only B';
  }
}

工厂

代码语言:javascript
复制
class Factory(){
  public function getProduct($type)
  {
    switch ($type) {
      case 'A':
        return new ProductA();
        break;

      case 'B':
        return new ProductA();
        break;

      default:
        # code...
        break;
    }
  }
}

用法

代码语言:javascript
复制
function someBussinessLogic($type)
{

  // ...ignore...

  $factory = new Factory;
  $product = $factory->getProduct($type);

  if ($type == 'B') {
    $product->SpecialMethod();
  }

  // ...ignore...
}

在用法中,我必须检查$type是否为'B‘。我觉得这种行为有点奇怪。我应该这么做还是把SpecialMethod交给interface Product?还是有更好的办法?

编辑

是的,我担心会有产品C,D,E.在未来,每个人都有自己独特的方法。如果我只是把所有的特殊方法放在接口上,接口就会变得非常庞大,所有其他产品都需要实现毫无意义的方法。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-04-10 06:28:08

我会这么做的

代码语言:javascript
复制
$product = $factory->getProduct($type);

if (is_a($product, ProductB::class)) {
   $product->SpecialMethod();
}

或者使用一个接口,如果您将有许多类与SpecialMethod,那么您可以检查接口,而不是单一的类。

供参考一个

检查给定对象是否属于该类,还是将该类作为其父类之一。

您也可以使用instanceOf

代码语言:javascript
复制
if ($product instanceof ProductB::class) {
   $product->SpecialMethod();
}

这里有一篇关于这两种差异的有用的文章

A和例子?

也是

我也不认为这有什么问题

代码语言:javascript
复制
interface ProductInterface
{
    public function getName();
    public function SpecialMethod();
}

但是,我也会在其中添加一个抽象类。

代码语言:javascript
复制
abstract class AbstractProduct impliments ProductInterface{
    abstract public function getName();
    public function SpecialMethod()
    {
        return ''; //or false
    }
}

class ProductA extends AbstractProduct {
    public function getName()
    {
        return 'A'; 
    }
}

class ProductB extends AbstractProduct {
    public function getName()
    {
        return 'A'; 
    }
    //override the concrete method in abstract class
    public function SpecialMethod()
    {
        return 'only B'; 
    }
}

这样,只要不依赖SpecialMethod获取某种类型的返回值,就可以在其他类中保留该方法的空值。我也会像我一样修改名字,但这只是我的偏好。

那你就能做到

代码语言:javascript
复制
$product = $factory->getProduct($type);
$product->SpecialMethod();  //return "only B" or ""

因为大多数类将固有抽象类中的空方法,只有那些实现其覆盖的产品才会起作用。如果多个产品都有这种方法,这是有意义的,但也可以创建一个单独的接口并检查它。因此,这更多地取决于SpecialMethod实际工作的具体情况。

票数 0
EN

Stack Overflow用户

发布于 2018-04-10 06:18:40

我得说这要看情况。如果您计划随着时间的推移将此方法添加到更多的类中,请选择该接口。如果有一些类,它仍然需要实现这个方法,但是有一个空的体,我不会认为这是不好的练习。这样,如果类C也要实现这个方法,您就可以摆脱if,而不必返回到代码中。

如果只有这一种特殊情况,我(个人)就会选择你已经拥有的。

或者,您可以调用调用someBusinessLogic()的特殊方法,因为在此语句之后没有任何后续操作。我的意思是:

代码语言:javascript
复制
someBusinessLogic($type)->specialMethod();

如果这种方法适用于您现有的代码,那么我强烈建议采用这种方式而不是if。

票数 0
EN

Stack Overflow用户

发布于 2018-04-10 06:39:17

工厂模式:对Wikipedia来说,工厂方法模式是一种创建模式,它使用工厂方法来处理创建对象的问题,而不必指定将要创建的对象的确切类。在这里,您提到的问题是调用$product->SpecialMethod()之前的检查;

如果我们遍历类实现,很明显,ProductB只需要specialMethod。因此,在someBussinessLogic($type)中,无论代码设计如何,实际上您只想在typeB的情况下调用specialMethod,因为在其他情况下没有specialMethod功能(为什么在所有情况下都要调用specialMethod?)。所以你自动需要一张支票。

另一方面,如果您正在编写泛型代码,则您的实体不应该有特定的行为。如果有,您应该将它们从泛型代码中插入,而不是在泛型代码中进行检查。

现在,由于您必须显式地处理这些检查,您可能想知道工厂模式对您有什么帮助?好吧,工厂模式在你想要改变一个特定类型的功能的时候就会发光,你会有一个点,你可以插入一个类,然后用新的功能插入更新的类。

底线是,如果您想要处理泛型代码中的特定行为,如上面所述,您的将不得不在代码中的某个地方编写检查。它最好在泛型模块之外,而不是损害泛型代码的完整性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49746532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档