我试着用工厂模式来创造产品。我为产品类创建了一个接口来实现和设计一个工厂,该工厂将根据传递给它的参数生成产品。
接口
interface Product
{
public function getName();
}产品
class ProductA implements Product{
public function getName()
{
return 'A';
}
}
class ProductB implements Product{
public function getName()
{
return 'B';
}
public function SpecialMethod()
{
return 'only B';
}
}工厂
class Factory(){
public function getProduct($type)
{
switch ($type) {
case 'A':
return new ProductA();
break;
case 'B':
return new ProductA();
break;
default:
# code...
break;
}
}
}用法
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.在未来,每个人都有自己独特的方法。如果我只是把所有的特殊方法放在接口上,接口就会变得非常庞大,所有其他产品都需要实现毫无意义的方法。
发布于 2018-04-10 06:28:08
我会这么做的
$product = $factory->getProduct($type);
if (is_a($product, ProductB::class)) {
$product->SpecialMethod();
}或者使用一个接口,如果您将有许多类与SpecialMethod,那么您可以检查接口,而不是单一的类。
供参考一个
检查给定对象是否属于该类,还是将该类作为其父类之一。
您也可以使用instanceOf
if ($product instanceof ProductB::class) {
$product->SpecialMethod();
}这里有一篇关于这两种差异的有用的文章
也是
我也不认为这有什么问题
interface ProductInterface
{
public function getName();
public function SpecialMethod();
}但是,我也会在其中添加一个抽象类。
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获取某种类型的返回值,就可以在其他类中保留该方法的空值。我也会像我一样修改名字,但这只是我的偏好。
那你就能做到
$product = $factory->getProduct($type);
$product->SpecialMethod(); //return "only B" or ""因为大多数类将固有抽象类中的空方法,只有那些实现其覆盖的产品才会起作用。如果多个产品都有这种方法,这是有意义的,但也可以创建一个单独的接口并检查它。因此,这更多地取决于SpecialMethod实际工作的具体情况。
发布于 2018-04-10 06:18:40
我得说这要看情况。如果您计划随着时间的推移将此方法添加到更多的类中,请选择该接口。如果有一些类,它仍然需要实现这个方法,但是有一个空的体,我不会认为这是不好的练习。这样,如果类C也要实现这个方法,您就可以摆脱if,而不必返回到代码中。
如果只有这一种特殊情况,我(个人)就会选择你已经拥有的。
或者,您可以调用调用someBusinessLogic()的特殊方法,因为在此语句之后没有任何后续操作。我的意思是:
someBusinessLogic($type)->specialMethod();如果这种方法适用于您现有的代码,那么我强烈建议采用这种方式而不是if。
发布于 2018-04-10 06:39:17
工厂模式:对Wikipedia来说,工厂方法模式是一种创建模式,它使用工厂方法来处理创建对象的问题,而不必指定将要创建的对象的确切类。在这里,您提到的问题是调用$product->SpecialMethod()之前的检查;
如果我们遍历类实现,很明显,ProductB只需要specialMethod。因此,在someBussinessLogic($type)中,无论代码设计如何,实际上您只想在typeB的情况下调用specialMethod,因为在其他情况下没有specialMethod功能(为什么在所有情况下都要调用specialMethod?)。所以你自动需要一张支票。
另一方面,如果您正在编写泛型代码,则您的实体不应该有特定的行为。如果有,您应该将它们从泛型代码中插入,而不是在泛型代码中进行检查。
现在,由于您必须显式地处理这些检查,您可能想知道工厂模式对您有什么帮助?好吧,工厂模式在你想要改变一个特定类型的功能的时候就会发光,你会有一个点,你可以插入一个类,然后用新的功能插入更新的类。
底线是,如果您想要处理泛型代码中的特定行为,如上面所述,您的将不得不在代码中的某个地方编写检查。它最好在泛型模块之外,而不是损害泛型代码的完整性。
https://stackoverflow.com/questions/49746532
复制相似问题