【发布时间】:2011-11-09 19:21:24
【问题描述】:
我有一组类似这样的类:
abstract class CollectionAbs implements Iterator {
public function GetListAsXml() {...}
public function GetItemsByFilter(criteria: array) {...}
public function Sort(comparisonFunction) {...}
public function AddItem(newItem: CollectionItemAbs);
public function RemoveItem(newItem: CollectionItemAbs);
public function UpdateItem(newItem: CollectionItemAbs);
protected itemList: array of CollectionItemAbs;
}
abstract class CollectionItemAbs {
abstract public function Save();
abstract public function Load();
abstract public function Delete();
public function GetAsXml(): string {...}
public function ItemMatchesFilter(criteria: array): boolean {}
protected property1;
protected property2;
}
这个想法是 CollectionItemAbs 实现的具体实例表示其数据来自数据库表中的一行的项目,CollectionAbs 的相应具体实例提供对这些项目实例的集合的操作,例如提供一个interator实现。抽象类提供大部分功能,但具体实例将提供特定于数据类型的附加功能,例如声明对应于其各自数据库表中的字段的额外属性。然后这两个类一起工作以执行所需的任何操作。
因此,例如,如果您调用 GetListAsXml(),它将遍历列表中的项目,对每个项目调用 GetAsXml(),将结果连接起来,并将其全部返回到适当的 XML 容器中。同样,调用 AddItem() 获取未保存的新项目对象并调用其 Save() 方法将其提交到数据库。要对集合进行排序,您只需调用 Sort(),传入一个比较两个项目的比较函数(抽象集合类本身提供了几个默认值,而实现类可以定义与它们唯一的集合项类型一起工作的其他默认值)。
现在,所有这些都假定整个集合已加载,并且由 CollectionAbs 实现实例中的构造函数处理。
那么,停在这里,这个设计体面吗?有没有可能更好的模式?我喜欢将管理单个项目的功能封装在项目类中,而将操作项目集合的功能封装在集合类中。而且,我喜欢 CollectionAbs 类可以为其子级提供如此多的功能,因为它需要关于项目的“内部知识”最少。
但是,在无法一次加载整个集合的情况下,我不太确定这种设计,因为这种情况要求集合和项目类之间进行更多、更紧密的通信,以及诸如一次加载单个记录的大量额外查询之类的事情。修改此设计以处理部分集合的最佳方法是什么?有什么我应该关注的模式吗?
如果重要的话,我会在 PHP 5.3 中执行此操作。
[编辑:在下面添加示例;还澄清了上面关于比较函数的错误陈述。]
因为有人询问如何在评论中使用它的示例:
这些类将构成大量各种类型的数据集合的基础。一个例子是跟踪系统其他部分使用的状态代码集。系统的不同部分使用映射到不同数据库表的略有不同的状态代码。所以我设置了这样的东西:
abstract class StatusCodeCollectionAbs extends CollectionAbs {
protected positionCompareFunction(item1, item2: StatusCodeAbs): integer {...};
protected descriptionCompareFunction(item1, item2: StatusCodeAbs): integer {...};
}
abstract class StatusCodeAbs extends CollectionItemAbs {
protected position: integer;
protected description: integer;
}
这两个类将作为所有状态码集合的基础。为了添加对特定集合的支持,我只创建了具体的子项:
class CustomerStatusCodeCollection extends StatusCodeCollectionAbs {
public function constructor() {
//load all items to list
}
//sort comparison closure unique to this status collection type
protected legacyCodeCompareFunction(item1, item2: CustomerStatusCode): integer {...};
}
class CustomerStatusCode extends StatusCodeAbs {
public function Load() {
//load this item from database
}
public function Save() {
//save this item to the database
}
//data unique to this status type
protected legacyCode: integer
}
系统的一个要求是通过更高应用层提供的一组统一的 CRUD 方法来管理所有收集数据。数据层中的这种层次结构通过为集合提供统一的接口来实现这一点,但仍然允许正确跟踪特定于集合类型的数据。有额外的状态代码层来跟踪系统将跟踪的数十种状态类型共享的公共数据;其他类型的集合可能在 CollectionAbs/CollectionItemAbs 下有自己的抽象层,也可以直接子类化 CollectionAbs 和 CollectionItemAbs,视需要而定。
【问题讨论】:
-
如果我有一个用例,我可以告诉你更多关于你的设计的信息。它似乎过于复杂,无法看到它的预期用途。
-
我添加了一个具体的例子。
-
在我下面的帖子中添加了一堆建议。
标签: php oop design-patterns