我已经在一个大型项目上工作了大约一年,最近我开始使用一种新的模式来显示数据。
背景
我有许多派生类将数据包装在 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>
<?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());
?>
问题
最后,我的实际问题是:这是一种已知的设计模式吗?我有什么主要缺点吗?我有理由不使用它吗?