目前,我使用抽象工厂来允许为生成请求对象指定自定义类名。我这样做的理由是允许我在不修改代码的情况下轻松地扩展核心功能。然而,最近,我对这种方法的有效性产生了一些怀疑。所以我的问题是:
允许工厂实例化,任何符合预期接口的提交的类名都是工厂概念的私生子化吗?为了避免这种情况,我会得到更好的服务吗?
更新
这里的逻辑是这样的:一方面,一个真实的汽车工厂(例如)如果没有配备制造这类汽车的机器,就不能创造出一辆汽车。另一方面,下面的代码就像给了同一家汽车工厂一个蓝图,使它原本不打算生产的定制汽车。
另一种方法是传入配置对象,指定可与工厂一起使用的自定义类名,并将工厂限制为只生成自定义类的,如果它与配置指定的自定义类名具体匹配的话。有什么想法吗?
相关的密码..。
<?php
interface AbstractRequestFactory
{
public function buildRequest($type);
}
class RequestFactory implements AbstractRequestFactory
{
public function buildRequest($type='http')
{
if ($type == 'http') {
return new HttpRequest();
} elseif ($type == 'cli') {
return new CliRequest();
} elseif ($custom = $this->makeCustom($type)){
return $custom;
} else {
throw new Exception("Invalid request type: $type");
}
}
protected function makeCustom($type)
{
if (class_exists($type, FALSE)) {
$custom = new $type;
return $custom instanceof RequestInterface ? $custom : FALSE;
} else {
return FALSE;
}
}
}
// so using the factory to create a custom request would look like this:
class SpecialRequest implements RequestInterface {}
$factory = new RequestFactory();
$request = $factory->buildRequest('\SpecialRequest');发布于 2012-02-10 00:53:50
你的东西看上去很不错。拥有一个工厂的目的是传递一些条件,并让该方法返回一个对象,假设该对象具有调用代码可用的相同的可调用方法。您是通过实现RequestInterface来执行这个假设的,因此只要任何自定义请求类都实现相同的接口,就不会出现“无法在非对象上调用函数”的场景。
有几项建议(只是个人偏好):
bool)
示例代码片段:
public static function getRequest($type='http')
{
switch ($type) {
case 'http':
return new HttpRequest();
case 'cli':
return new CliRequest();
case 'myCustom1':
return new MyCustom1();
case 'myCustom2':
return new MyCustom2();
default:
throw new Exception("Invalid request type: $type");
}
}
$request = RequestFactory::getRequest($type);
// As long as all objects in factory have access to same methods
$request->doSomething();
$request->andDoSomethingElse();
// Otherwise you end up with that feared 'unable to call function on non-object'
$request->iAmASneakyMethodNotEnforcedByAnInterfaceOrAvailableByExtension(); 发布于 2012-02-10 00:41:26
这是相当主观的,因此以下只是一个观点:
我不会很快用这样的东西。如果您只有少数几个工厂会关心的类,那么我只需要对它们进行硬编码。但如果你有大量的这些,我认为这是合适的。
考虑到您正在验证类是否扩展了适当的接口,我想说的是,您所做的工作没有什么问题,因为它是故障安全的。使用工厂方法的代码看起来是干净的,我认为这是最重要的事情。
如果你在各地使用这样的技术,那么我会反对它。但是,由于这是隐藏在实现中的,我认为您可以在做一些稍微不合适的事情时有更多的回旋余地。
发布于 2012-02-10 01:02:06
为什么不使用调度数组呢?即
class RequestFactory
{
private static $requests = array(
'http' => 'HttpRequest',
'cli' => 'CliRequest',
'summatelse' => 'Summat'
);
public static GetRequest($type)
{
if (array_key_exists($type, $requests)) return new $requests[$type];
else throw new Exception("Invalid request type: $type");
}
}https://stackoverflow.com/questions/9220939
复制相似问题