Mar*_*ace 1 php oop design-patterns
我有一个像这样的构造函数:
public function __construct($data)
{
$this->_data = new SimpleXMLElement($data);
}
Run Code Online (Sandbox Code Playgroud)
哪个好.但是,我想提供传递simplexmlelement或字符串的机会.
就像是:
public function __construct($data)
{
if (is_string($data)) {
$data = new SimpleXMLElement($data);
}
$this->_data = $data;
}
Run Code Online (Sandbox Code Playgroud)
这是不好的做法吗?
我的想法是,客户端代码可以决定它想要预先做多少工作.但它会导致任何问题吗?
好吧,解决这个问题的一种方法是将问题排除在外,实际上非常简单:
public function __construct(SimpleXMLElement $data)
{
$this->_data = $data;
}
Run Code Online (Sandbox Code Playgroud)
然后,您只需在其中传递一个SimpleXMLElement,并可以决定何时构造对象,如果它来自字符串或其他SimpleXMLElement,或者不是.
如您所见,这使代码更加灵活.遵循两个简单的规则:
new在构造函数中使用关键字.if.如果您现在想知道在哪里可以放置代码来创建对象(例如,如果这是一些逻辑,您将在多个地方使用并且您害怕复制它),您可以考虑添加一些静态辅助方法:
public static function createFromXmlString($string) {
return static::createFromSimpleXmlElement(
simplexml_load_string($string)
);
}
public static function createFromSimpleXmlElement(SimpleXMLElement $element) {
return new static($element);
}
public function __construct(SimpleXMLElement $data)
{
...
Run Code Online (Sandbox Code Playgroud)
用法:
$foo = foo::createFromXmlString('<root/>');
Run Code Online (Sandbox Code Playgroud)
或者创建一个执行作业的工厂对象(将对象创建代码移离对象).
静态全局类方法通常更容易引入,因此您通常可以动态编写它们,但大多数情况下,如果有两个以上开始考虑如何再次删除这些函数,例如将代码移动到工厂中.
这个[构造函数处理多种输入类型]是不是很糟糕的做法?
它有点,因为你new在构造函数中使用了关键字.它会破坏测试,你之后使用的类名new是一个隐藏的依赖项(你不需要那些;看看为什么不"在对象构造函数中实例化一个新对象"? [实际上这不是一个很好的问答,只是寻找代码嗅觉关于这个以及控制/依赖注入的反转的讨论 - 更新:更多这种材料在我的脑海中:缺陷:构造函数做真正的工作(2008年11月;由MiškoHevery)(在Youtube上也有这个人的视频) ,他有很好的口音和良好的风格来解释事情)])
不良做法的另一部分是你倾向于在同一个构造函数中添加越来越多的案例来处理.所以它随着时间而变化,而实际上对象并没有真正改变.
我认为这是一个常见的错误(也是快捷方式),因为生活中没有那么多的是非,只是试着找出适合自己的决定点.已经问过这里是一个好兆头我会说,你开始提高你的感官.
我的想法是,客户端代码可以决定它想要预先做多少工作.但它会导致任何问题吗?
首先,对"客户端"代码和目标代码之间的区别是非常好的理解.您清楚地表明您认为的好处.
另一方面,一个对象应该一次做一件事,并且创建一个新对象是一个关键阶段.如果你开始在构造函数中加入很多代码和逻辑,那么事情就会变得复杂.它只是一个非常重要的地方,无法引入复杂的代码(例如,任何超过三行的内容都很复杂).构造函数应该只初始化新对象,就是这样.
无论我在答案的第一部分给出了什么建议,更多的OOP风格可能如下:
abstract class Foo {...}
class FooString extends Foo {
public function __construct($string) {
...
}
}
class FooSimpleXML extends Foo {
public function __construct(SimpleXMLElement $element) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
你有一个类型/对象,这是Foo.随着代码库的增长,您的客户端代码对于获取来源有不同的要求Foo,但它总是需要一个Foo.通过创建基本类型的子Foo类型,不得更改旧代码,并且可以为更改的需求添加新代码.
这可能是最干净的方法,但是,您需要知道这Foo是不同类型而不是某种辅助对象.