我已经在一个大型项目上工作了大约一年,最近我开始使用新模式来显示数据。
背景
我有许多派生类将数据包装在1:1链接的sql表及其相应的基类中。我的目标是将任何和所有显示代码保持在业务逻辑中,并且任何和所有SQL /业务逻辑都远离显示代码。我认为这在我的案例中是很好的做法,使代码更加模块化,并允许引入不同的显示媒体。我遇到的一个问题是,数据类具有通用显示功能更合乎逻辑,其中实际的显示介质(html,json,xml)可能会在以后添加。我在一些类中有一些递归绘图函数会使绘制函数排除非常困难。我的第一个想法是为我想要显示的每种类型创建另一个派生类,它只是以所需的方式实现显示功能,但这打破了我所遵循的另一种模式。我使用工厂方法来实例化大多数这些类。提供了一个ID,它从数据库中提取元数据,以便知道哪个表以及应该链接到哪个相应的类。所以,在这种情况下,我需要知道我在显示它之前显示的内容(HTML,JSON等等),这在我的情况下也不会起作用,因为它会破坏工厂。
我的解决方案
我创建了一个静态类,其中包含每个显示媒体的“显示器”功能。在这一点上,我正在利用这个类作为更多的容器。此“dispalyer”类中的函数返回一个匿名函数,该函数将显示所需类的实例。它返回它从对象成员构建的任何可显示数据字符串。这样我就可以在我的任何课程上调用.display()
,并简单地将其传递给所需类型的显示器:page->display(PageDisplayer::asHTML());
我认为它看起来很干净,并且允许逻辑与显示代码分开,同时将特定的显示代码保存在一个有组织的区域中。
下面是一个非常简单的示例,不包括我正在处理的所有工厂方法和继承级别。 (这段代码有错误,我没有在工作环境中写这个 - 它可能不会“编译”)
主要逻辑/模型
<?php
class UserData {
private $ID;
private $name;
public function __construct($ID, $name) {
$this->ID = $ID;
$this->name = $name;
}
public getID() {
return $this->ID;
}
public getName() {
return $this->name;
}
public function display($displayer) {
return $dispalyer($this);
}
}
?>
显示器类
<?php
class UserDataDispalyer {
static function asHTML() {
return function($userData) {
$out = '<div id="' . $userData->getID() . '">';
$out .= $userData->getName();
$out .= "<div>";
return $out;
}
}
static function asJSON() {
return function($userData) {
return json_encode(array("ID" => $userData->getID(), "name" => $userData->getName()));
}
}
}
?>
这是前端渲染代码的样子
HTML页面
<html>
<?php
$userData = new UserData(12345, "John");
echo $userData->display(UserDataDispalyer::asHTML());
?>
</html>
JSON API
<?php
$userData = new UserData(12345, "John");
echo $userData->display(UserDataDispalyer::asJSON());
?>
问题
最后,我的实际问题:这是一个已知的设计模式吗?我缺少哪些主要缺点?我不应该使用这个吗?
答案 0 :(得分:2)
我认为你所做的事情没有名字,而且确实不应该这样。这是何时使用界面和strategy pattern的教科书示例。
您的方法的缺点是您可以将任意函数传递给display
并获得各种错误。使用接口,确保传递给display
的唯一参数是某种类型(下面,类型是UserFormatter)。
以下是相同代码的示例,但使用的是接口。
interface UserFormatter {
public function get($user);
}
public HTMLFormatter implements UserFormatter {
public function get($user) {
return "<div id=\"{$user->getID()}\">{$user->getName()}</div>";
}
}
public JSONFormatter implements UserFormatter {
public function get($user) {
return json_encode(array('ID' => $user->getID(),
'name' => $user->getName()));
}
}
在userData
课程中,您将拥有
public function display(UserFormatter $formatter) {
return $formatter->get($this);
}
此外,您的userData
课程应命名为UserData
。类总是在CamelCase中。