PHP   发布时间:2022-04-04  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了php-面向对象设计的建议:项目集合大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

我有一组这样的类:

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中执行此操作.

[编辑:在下面添加示例;还澄清了上面关于比较函数错误之处.]

由于有人要求提供有关如何在@L_673_32@中使用该示例的示例:

这些类将构成大量各种类型数据收集的基础.一个示例是跟踪系统其他部分使用的状态代码集.系统的不同部分使用略有不同的状态码,它们映射到不同的数据库表.所以我建立了这样的东西:

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子类化.

解决方法:

一些设计要点:

>如何从数据库加载集合?您已经提到了这一点,但这是设计的基础.而且,我会说您不应该为此提供认实现.

>解决此问题的常用方法是传递一个表示数据库中唯一ID的整数数组.如果您要让Item和Items共享同一接口,请不要通过类型检查来强制执行此操作.一个Item只需要一个id,而Items则需要一个数组. PHP的重载非常糟糕,因此我不会强制使用数组来简化重载.

>如何节省工作?从外观上看,每个节点都必须与数据库紧密结合才能知道如何保存.那可能是好事,也可能是坏事,但是无论哪种方式,您都需要虑一下.我可能会建议进一步分离(分离它们).
>我会使用接口和抽象.下面的代码对此有更详细的说明.
>除了进行排序外,我还将添加一种认方式来比较项目.

>我将在您的Item类中定义compareTo().
>在您使用时,我还将定义一个equals()方法.

> Xmlserialize应该是一个单独的接口.老实说,我希望PHP本身具有这样的接口.它有很多用途.
>实现Countable使您可以使用PHP本机count().这是PHP@L_262_61@大小的方法.轻松完成,不妨将其放入.

总体而言,您做得很好,但是我有一些建议.

下面的代码并不完美,也不完整,因为它不能解决我上面提出的一些问题.但是,它确实提供了比您提供的功能更多的功能.还要注意,我已将其重命名为ActiveNode而不是CollectionItem等.这对我来说更有意义.

<?PHP
/**
 * resource exception would represent a problem with a resource such as a
 * database connection or a service like an API.  Not everything uses a database
 * these days.
 */
class resourceException extends RuntimeException {}

/**
 * A database resource exception.
 */
class DatabaseException extends resourceException {}

/**
 * Allows you to convert an item to and from XMl.
 */
interface Xmlserializeable {
    /**
     * @return String A String in XML format represenTing the object.
     */
    public function xmlserialize();

    /**
     * @param String $xml A String in XML format represenTing the object.
     * @throws InvalidArgumentexception if the $xml is not well-formed.
     * @throws InvalidArgumentexception if the $xml does not represent the correct object.
     */
    public function xmlUnserialize($xml);
}

/**
 * Allows you to sort an object.
 */
interface Sortable {
    /**
     * Sorts the collection with the function provided.  If none is provided, it
     * will simply use compareTo on each item.
     * @param function $fn The sorTing function. 
     */
    function sort($fn=null);
}

/**
 * An active node.  An active node contains methods to save, load, delete,
 * convert to XML, etc.  it is 'active' because it is tied to the resource it
 * represents.
 */
interface IActiveNode extends XMLserializeable {

    /**
     * Saves the item to the database.
     * @throws DatabaseException if an error occurs during the save.
     */
    public function save();

    /**
     * Loads the item from the database.
     * @throws DatabaseException if an error occurs during the load.
     */
    public function load();

    /**
     * deletes the item from the database.
     * @throws DatabaseException if an error occurs during the deletion.
     */
    public function delete();

    /**
     * Compares an item to another.
     * @param IActiveNode $node The node to compare to.
     * @return int a negative number for less than, 0 for equality, and a positive number for greater than.
     * @throws InvalidArgumentexception if the item provided cAnnot be compared to.
     */
    public function compareTo(IActiveNode $nodE);

    /**
     * Tests for equality against the provided item.
     * @param IActiveNode $node The node to compare to.
     * @return Boolean if the nodes are equal.
     */
    public function equals(IActiveNode $nodE);
}

/**
 * A collection of active nodes.  Note that you should override behavior of many
 * off the methods this inherits to ensure that 
 */
interface IActiveNodes extends IActiveNode, Sortable, Countable, Iterator {
    /**
     * Adds a node to the collection.
     * @param IActiveNode $node The IActiveNode to add.
     * @return int The index the node was added into.
     * @throws InvalidArgumentexception if the IActiveNode is the wrong type for this collection.
     */
    function addNode(IActiveNode $nodE);

    /**
     * Removes a node from the collection. Uses the equals method. Nodes will be
     * reordered after a remove.
     * @param IActiveNode $node The IActiveNode to remove.
     * @return IActiveNode The removed node.
     * @throws InvalidArgumentexception if the IActiveNode is the wrong type for this collection.
     */
    function removeNode(IActiveNode $nodE);

    /**
     * Gets an item from the list.
     * @param IActiveNode $node The node to retrieve.
     * @return IActiveNode The IActive node that matches the one provided.
     */
    function getNode(IActiveNode $nodE);
    /**
     * checks to see if a node exists in the collection. Uses the equals method.
     * @param IActiveNode $node The IActiveNode to check for containment.
     * @return Boolean Returns true if the IActiveNode is in the collection.
     * @throws InvalidArgumentexception if the IActiveNode is the wrong type for this collection.
     */
    function contains(IActiveNode $nodE);

    /**
     * Gets an item from the list.
     * @param int $index The index to retrieve.
     * @return IActiveNode The IActive node at the index provided.
     * @throws InvalidArgumentexception if the index is not an Integer.
     * @throws OutOfBoundsException if the index is out of bounds.
     */
    function geTindex($indeX);

    /**
     * Removes an item from the list by index.
     * @param int $index The index to remove.
     * @return IActiveNode The IActive node at the index provided.
     * @throws InvalidArgumentexception if the index is not an Integer.
     * @throws OutOfBoundsException if the index is out of bounds.
     */
    function removeIndex($indeX);

    /**
     * Filters the collection with a function.  It calls the filter function on
     * each item in the collection, and if the filter function returns true, then
     * it will add that to a new IActiveNodes collection, and return it.
     * @param function $fn A filter function.
     * @return IActiveNodes The filtered nodes.
     */
    function filter($fn);

}

?>

笔记:

>定义实现接口以提供某些认行为的抽象类.在某些情况下,使接口与抽象分离对我很有用.如果所有开源软件都将变得越来越重要.
>与返回布尔值相比,抛出异常确实很棒.似乎您可能了解这一点,但值得注意.请注意,我已经使用异常来表示资源不可用.出错时具有定义的行为很有用.
>我在将IActiveNode作为参数的任何对象上抛出InvalidArgumentexceptions.这允许您扩展IActiveNodes,并且该扩展仅适用于某些类型.很有用.
>我的解决方案正在接近Java之类的东西.我会说,根据您要采用的语言,我建议您使用其他语言(尽管不一定是Java).
>如果您希望列表在语法上可以像数组一样对待,那么我也经常实现ArrayAccess.

老实说,我不介意与您谈论更多.请随时与我联系.

大佬总结

以上是大佬教程为你收集整理的php-面向对象设计的建议:项目集合全部内容,希望文章能够帮你解决php-面向对象设计的建议:项目集合所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: