我正在尝试实施我认为的工厂类。我有一个API框架。在我的前端控制器处理完请求后,它会尝试将输出返回给客户端。我的前端控制器中的调用如下所示:
<?php
...
$response_obj = new Response($response_str, 'json');
echo $response_obj->render();
?>
我的Response
类基本上将第二个参数作为要实例化的类的类型,并将此新类传递给$response_str
的内容。这是:
<?php
class Response {
public function __construct($data, $format) {
switch ($format) {
case 'json':
$obj = new ResponseJson($data);
break;
}
return $obj;
}
}
然后我的ResponseJson
课程如下:
<?php
class ResponseJson {
protected $data;
public function __construct($data) {
$this->data = $data;
return $this;
}
public function render() {
header('Content-Type: application/json');
return json_encode($this->data);
}
}
但是,在我的前端控制器中$response_obj
将其类型返回为Response
而不是ResponseJson
,如预期的那样,并调用render()
方法(存在于ResponseJson
而非Response
)会导致致命错误:
致命错误:在第61行的/Users/Martin/Sites/api-framework/index.php中调用未定义的方法Response :: render()
我哪里错了?
答案 0 :(得分:3)
您所描述的不是工厂,而是无效的代码。 (__construct将始终返回它实现的类的新实例。事实上,它不需要返回任何东西,因为这没有效果!)
工厂通常实现为静态函数,可以在不实例化工厂类对象的情况下调用。然后它创建一个类的对象实例(在大多数情况下是另一个类,如你的情况)并返回它。
您的Response类应如下所示:
<?php
class Response {
static public function create($data, $format) {
switch ($format) {
case 'json':
$obj = new ResponseJson($data);
break;
case default:
return NULL; // or throw exception!
break;
}
return $obj;
}
}
和你的前端控制器一样:
<?php
...
$response_obj = Response::create($response_str, 'json');
echo $response_obj->render();
?>
答案 1 :(得分:1)
我认为你误解了工厂模式:
构造函数方法在类的实例化时作为对象自动调用,我相信你知道。
对象的实例化将始终返回对象本身,它违背了很多逻辑,以便对象的实例化返回除自身以外的任何东西,尤其是不同类型的对象。由于这个规则,构造函数方法不能返回,它将始终只在实例化时调用,从而返回对象本身。
我对你的背景并不完全清楚,但在这种情况下你想要一个工厂似乎很奇怪,我希望ResponseJson能够扩展Response而不是由它创建。
希望这有帮助!
答案 2 :(得分:1)
如果您确实想要实现工厂模式,可以执行以下操作:
//Pseudo-code
class ResponseFactory
{
createJSONResponse($data)
{
return new JSONResponse($data);
}
createXMLResponse($data)
...
createDefaultResponse($data)
{
return createJSONResponse($data);
}
}
虽然,对于响应类型(其中可能只有2或3个),我想我会选择Kaii的静态工厂方法。
在回复您的评论时,我更喜欢标准工厂的原因,每种方法都如上所述,而不是:
createResponse($type, $data)
{
if ($type == 'json')
return new JSONResponse($data);
else if (...)
...
}
特别是因为在很多情况下你的来电者看起来像:
$response = createResponse('json', $data);
我更喜欢这个:
$response = createJSONResponse($data)
虽然我应该注意到php将字符串作为函数调用的能力可以使一个非常优雅(虽然有点不安全)的抽象工厂。