PHP - 工厂的产品有特殊的方法
PHP - a product of a factory has special method
我尝试使用工厂模式来创建产品。我为产品创建了一个接口 类 来实现和设计一个工厂,该工厂将根据传递给它的参数生成产品。
界面
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...,每个产品都有自己的特殊方法。如果我把所有特殊的方法都放在接口上,接口会变得很大,其他产品都需要实现无意义的方法。
我会说这取决于。如果您打算随着时间的推移将此方法添加到更多 classes,请选择接口。如果有一些 classes,我不认为这是不好的做法,它们仍然必须实现这个方法但有一个空的主体。这样你就可以摆脱你的 if 而不必回到你的代码,如果 class C
也会实现这个方法。
如果只是这一种特殊情况,我(个人)会像您已经拥有的那样去寻找。
或者您可以在调用 someBusinessLogic()
的地方调用特殊方法,因为在该语句之后没有任何内容。我的意思是:
someBusinessLogic($type)->specialMethod();
如果这种方法适用于您现有的代码,我强烈建议您采用这种方式而不是 if。
我会这样做
$product = $factory->getProduct($type);
if (is_a($product, ProductB::class)) {
$product->SpecialMethod();
}
或者如果您有许多 class 带有 SpecialMethod
的接口,那么您可以检查接口而不是单个 class.
供参考is_a
Checks if the given object is of this class or has this class as one of its parents.
您也可以使用instanceOf
if ($product instanceof ProductB::class) {
$product->SpecialMethod();
}
这里有一个有用的post关于两者之间的区别
What is the difference between is_a and instanceof?
还有
我也没看出这有什么本质上的错误
interface ProductInterface
{
public function getName();
public function SpecialMethod();
}
不过我还要在其中添加一个摘要 class。
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';
}
}
这样您就可以在其他 class 中将该方法留空,只要您不依赖 SpecialMethod
获取某种类型的 return 值。我也会像我一样修改名称,但这只是我的偏好。
那么你可以这样做
$product = $factory->getProduct($type);
$product->SpecialMethod(); //return "only B" or ""
因为大多数 classes 将继承抽象 class 中的空方法,只有那些实现其覆盖的产品才会有所作为。如果多个产品都具有该方法,这是有道理的,但制作一个单独的界面并检查它也很有意义。所以它更多地取决于 SpecialMethod
实际做什么的细节。
工厂模式:对维基百科来说,工厂方法模式是一种创建模式,它使用工厂方法来处理创建对象的问题,而不必指定将要创建的对象的确切 class。
这里你提到的问题是调用 $product->SpecialMethod();
之前的检查如果我们通过 class 实现很明显ProductB只需要specialMethod。所以在 someBussinessLogic($type) 中,不管代码设计如何,实际上你只想在 [= 的情况下调用 specialMethod 12=]typeB,因为在其他情况下没有 specialMethod 功能(例如为什么要调用 specialMethod所有的情况?)。所以你自动需要一张支票。
另一方面,如果您正在编写通用代码,您的实体不应该有特定的行为。如果有,您应该将它们从通用代码中插入,而不是在通用代码中进行检查。
现在,由于您将不得不明确地处理此类检查,您可能想知道工厂模式如何帮助您?。好吧,当您想更改特定类型的功能时,工厂模式会大放异彩,您将有一个点,可以从那里插入 class 并插入具有新功能的更新后的 class .
底线是,如果您想在通用代码中处理特定行为,如上述情况,您 将 必须在代码中的某处写一个检查。最好在通用模块之外,而不是损害通用代码的完整性。
我尝试使用工厂模式来创建产品。我为产品创建了一个接口 类 来实现和设计一个工厂,该工厂将根据传递给它的参数生成产品。
界面
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...,每个产品都有自己的特殊方法。如果我把所有特殊的方法都放在接口上,接口会变得很大,其他产品都需要实现无意义的方法。
我会说这取决于。如果您打算随着时间的推移将此方法添加到更多 classes,请选择接口。如果有一些 classes,我不认为这是不好的做法,它们仍然必须实现这个方法但有一个空的主体。这样你就可以摆脱你的 if 而不必回到你的代码,如果 class C
也会实现这个方法。
如果只是这一种特殊情况,我(个人)会像您已经拥有的那样去寻找。
或者您可以在调用 someBusinessLogic()
的地方调用特殊方法,因为在该语句之后没有任何内容。我的意思是:
someBusinessLogic($type)->specialMethod();
如果这种方法适用于您现有的代码,我强烈建议您采用这种方式而不是 if。
我会这样做
$product = $factory->getProduct($type);
if (is_a($product, ProductB::class)) {
$product->SpecialMethod();
}
或者如果您有许多 class 带有 SpecialMethod
的接口,那么您可以检查接口而不是单个 class.
供参考is_a
Checks if the given object is of this class or has this class as one of its parents.
您也可以使用instanceOf
if ($product instanceof ProductB::class) {
$product->SpecialMethod();
}
这里有一个有用的post关于两者之间的区别
What is the difference between is_a and instanceof?
还有
我也没看出这有什么本质上的错误
interface ProductInterface
{
public function getName();
public function SpecialMethod();
}
不过我还要在其中添加一个摘要 class。
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';
}
}
这样您就可以在其他 class 中将该方法留空,只要您不依赖 SpecialMethod
获取某种类型的 return 值。我也会像我一样修改名称,但这只是我的偏好。
那么你可以这样做
$product = $factory->getProduct($type);
$product->SpecialMethod(); //return "only B" or ""
因为大多数 classes 将继承抽象 class 中的空方法,只有那些实现其覆盖的产品才会有所作为。如果多个产品都具有该方法,这是有道理的,但制作一个单独的界面并检查它也很有意义。所以它更多地取决于 SpecialMethod
实际做什么的细节。
工厂模式:对维基百科来说,工厂方法模式是一种创建模式,它使用工厂方法来处理创建对象的问题,而不必指定将要创建的对象的确切 class。
这里你提到的问题是调用 $product->SpecialMethod();
之前的检查如果我们通过 class 实现很明显ProductB只需要specialMethod。所以在 someBussinessLogic($type) 中,不管代码设计如何,实际上你只想在 [= 的情况下调用 specialMethod 12=]typeB,因为在其他情况下没有 specialMethod 功能(例如为什么要调用 specialMethod所有的情况?)。所以你自动需要一张支票。
另一方面,如果您正在编写通用代码,您的实体不应该有特定的行为。如果有,您应该将它们从通用代码中插入,而不是在通用代码中进行检查。
现在,由于您将不得不明确地处理此类检查,您可能想知道工厂模式如何帮助您?。好吧,当您想更改特定类型的功能时,工厂模式会大放异彩,您将有一个点,可以从那里插入 class 并插入具有新功能的更新后的 class .
底线是,如果您想在通用代码中处理特定行为,如上述情况,您 将 必须在代码中的某处写一个检查。最好在通用模块之外,而不是损害通用代码的完整性。