【问题标题】:Looking for specific design pattern寻找特定的设计模式
【发布时间】:2009-04-30 05:51:45
【问题描述】:

我正在寻找描述某种情况的模式。也许有人知道一些事情,可以给我一个提示

情况 A 类型的对象,与 B 类型的对象的 1 : n 关联。示例:A 人和他的所有宠物。宠物对象有一个年龄数据成员。现在每个人都应该有一个关于他的宠物平均年龄的数据成员。我不希望保存和加载这些信息,而是在加载过程中计算(所有必要的信息都已经存在,所以有点多余,但我想要 person 对象中的信息)。

问题 那么我怎样才能以面向对象的方式做到这一点呢?是否有描述这种情况的模式?我的第一个想法是创建一个类 ComputedFieldsUpdater,它接受一个宠物对象,然后计算所有尚未加载的字段。但我想知道这是否是正确的方法,或者是否有更优雅的解决方案?

感谢您的意见。

【问题讨论】:

    标签: design-patterns


    【解决方案1】:

    如果您为关联类型创建一个类以键入 B,这相当简单:无论如何您都需要某种列表。所以只需创建一个“PetList”或类似的东西,它有一个方法“averageAge()”,它从所有宠物中计算这个值。

    现在您可以致电person.getPets().averageAge() 获取平均值。

    从面向对象的角度来看,关于平均值的信息不应该直接存在于 Person-object 中。

    【讨论】:

    • 更好的平均值然后可以缓存而不是每次重新计算
    • “从面向对象的角度来看,关于平均值的信息不应该直接存在于 Person-object 中。” - 我不太确定这一点。通常在 OOP 中,一些代码想要让某个类为其执行计算——而不用担心数据的内部或中间表示。我认为像 person.getPetsAverageAge() 这样的方法会是一个合适的方法。
    • 但这会违反单一责任原则。据我了解,一个 Person 类负责表示一个人的抽象概念。如果您还让它负责对关联类进行计算,那么您就赋予了它第二个职责。当然,除非 Person 的唯一目的是进行这些计算而不代表一个人。但命名具有很大的误导性。
    【解决方案2】:

    它不是四人组设计模式,但是当绝对有必要存储计算冗余的数据时,普遍接受的解决方案是延迟加载它,然后保留一个布尔值值来描述它是否仍然有效。

    换句话说:

    class Person
    {
    List<Pet> myPets;
    float averageAge;
    boolean isAgeValid = false;
    
    float getAverageAge()
    {
        if(isAgeValid)
            return averageAge;
        else
            ...calculate age, save it in averageAge, set bool to true, and return derived float...
    }
    
    //all list operations should mark the bool false
    void Add(Pet p)
    {
        myPets.Add(p);
        isAgeValid=false;
    }
    }
    

    【讨论】:

    • 您还可以设置一个 Person 方法,让宠物在其内部状态/年龄更改时调用,将 isAgeValid 设置为 false。将其标记为公共(或更恰当地在设计级别,包)可以正常工作,因为在不适当的时间调用它不会损坏任何数据,它只会导致额外的计算。
    • 我真的很想将 A 类和 B 类正确分开。这就是为什么我首先考虑将更新代码放在一个单独的类中。
    • 正确的分离可能是上面的答案,其中有一个为 Pet 类型的通用集合的子类,它添加了此功能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多