假设我有以下类,其实例为e.x存储其属性某处。在JSON文件或数据库中:
Class Foo
abstract class Foo
{
protected $ID;
protected $title;
// getters and setters
}
Class Bar(扩展Foo)
class Bar extends Foo
{
protected $text;
// getters and setters
}
Class Baz(也扩展为Foo)
class Baz extends Foo
{
protected $tabs = array();
// getters and setters
}
从数据源加载它们的最佳方法是什么?
我的抽象类Foo
有一个方法load($ID, PDO $pdo)
。 Bar
和Baz
覆盖了此方法,它扩展了title
类中Foo
属性的常规加载,并使用了必须加载的属性。
所以在代码中,这看起来像这样:
Class Foo
abstract class Foo
{
protected $ID;
protected $title;
public static function load($ID, PDO $pdo)
{
$result = null;
// SQL query for getting $title property into $result
return $result;
}
// getters and setters
}
在班级栏中,我这样做:
class Bar extends Foo
{
protected $text;
public function __construct(stdClass $data)
{
$this->ID = $data->ID;
$this->text = $data->text;
}
public static function load($ID, $pdo)
{
$generalInfo = parent::load($ID, $pdo);
$result = null;
// PDO query for getting $text property into $result
$generalInfo->text = $result;
return $generalInfo;
}
// getters and setters
}
所以这让我调用$dataToCreateInstance = Bar::load(4, $pdoInstance)
并返回所需的信息,以实现ID为4的特定Bar
对象。
这里的问题是(正如你所看到的)我的类被绑定到PDO,为每个数据源实现load
方法真的很难看,所以它根本不是通用的
我现在正在寻找一种模式,让我可以从任何来源加载这些类。我想到了Loader
类看起来像这样:
class LoaderManager
{
/**
* @var Loader[]
*/
protected $loaders = array();
public function registerLoader($className, $loaderClass)
{
$this->loaders[$className] = $loaderClass;
}
public function loadClass($class, $ID)
{
return $this->loaders[$class]->load($ID);
}
}
并使用抽象的Loader类
abstract class Loader
{
public abstract function load($ID);
}
所以现在我把事情解耦了。这种尝试的问题是我总是为类本身提供额外的Loader
。因此,对于课程Bar
,我必须提供BarLoaderPDO
或BarLoaderJSON
中的至少一个。这在某种程度上并不那么优雅,而且感觉有些错误"。
还有一个问题是我必须存储当前应用程序中哪个类必须使用哪个加载器的映射。
但这是我能想到的唯一一次让我想到的东西。
我现在喜欢讨论并听取是否有其他(更好的)尝试以及如何实现这些尝试。
答案 0 :(得分:0)
我想说一个好的设计你最终会在你的代码中使用不同的设计模式,所以通常,模板方法,依赖注入,工厂模式以及封装和数据隐藏等概念都是诀窍。尝试封装行为并使用数据隐藏,不要让对象泄漏内部信息,所以看看Demeter´s Law。这里有一些样本设计:
$DirStar="C:\Temp\test"
$Before1980="C:\Temp\Scans\1900s"
$After1980="C:\Temp\Scans\2000s"
Get-ChildItem $DirStar -file -Filter "*.tif" | where basename -Match "^\d{4}$" | %{
if ([int]$_.BaseName -le 1980)
{
move-item $_.FullName $Before1980
}
else
{
move-item $_.FullName $After1980
}
}
答案 1 :(得分:0)
您可以实现。 请参阅CodeIgnitor中的Loader类实现。 您还需要使用自动加载类,并根据变量动态创建对象的实例。
这里是可能的实施链接。 https://github.com/bcit-ci/CodeIgniter/blob/develop/system/core/Loader.php
祝你好运。