“Brokered definition set”设计模式 - 以另一个名称着称?

时间:2008-12-30 22:29:07

标签: design-patterns registry singleton

在我参与多年的项目中,我逐渐发展出一种被证明对我非常有用的设计模式。我有时觉得我应该对它有点福音派,但如果我尝试并发现它只是我某人的旧帽子版本,我会有点尴尬。我已经挖掘了设计模式徒劳地寻找它,我没有遇到任何其他人谈论它,但我的搜索并不详尽。

核心思想是拥有一个代理对象来管理一组定义对象,每个定义对象构成一些复杂属性的可能值。例如,您可能拥有CarType,Plane和Generator类,它们都具有EngineType。 Car不存储自己的EngineType对象,它存储某种类型的引用键,表示它具有的引擎类型(例如整数或字符串ID)。当我们想要查看EngineType的属性或行为时,比如说WankelEngine,我们要求EngineTypeBroker单例对象获取WankelEngine的定义对象,并将其传递给引用键。这个对象封装了有关EngineTypes的有趣内容,可能只是一个属性列表,但也可能将行为加载到它上面。

所以它的促进是一种共享的,松散耦合的聚合,其中许多汽车可能有一个WankelEngine但只有一个WankelEngine定义对象(并且EngineTypeBroker可以替换该对象,利用松散耦合到增强的运行时态射)。

我使用它时这个模式的一些元素(继续使用EngineType作为例子):

  1. 始终存在IsEngineType(x)和EngineType(x)函数,用于确定给定值是否为EngineType的有效引用键,以及是否分别检索与引用键对应的EngineType定义对象。
  2. 我总是允许给定EngineType的多种形式的引用键,始终至少是一个字符串名称和定义对象本身,通常是一个整数ID,有时是聚合EngineType的对象类型。这有助于调试,使代码更灵活,并且在我的特定情况下,相对于旧的实践,减轻了许多向后兼容性问题。 (在这个项目的上下文中,人们习惯做这一切的常用方法是为EngineType可能具有的每个属性定义哈希,并通过引用键查找属性。)
  3. 通常,每个定义实例都是该定义类型的通用类的子类(即WankelEngine继承EngineType)。定义对象的类文件保存在/ Def / EngineType等目录中(即WankelEngine的类为/ Def / EngineType / WankelEngine)。因此,相关定义组合在一起,类文件类似于EngineType的配置文件,但能够定义代码(通常不在配置文件中找到)。
  4. 一些简单的说明性样本伪代码:

    class Car {
    
        attribute Name;
        attribute EngineTypeCode;
    
        object GetEngineTypeDef() {
            return EngineTypeBroker->EngineType(this->GetEngineTypeCode());
        }
    
        string GetDescription() {
            object def = this->GetEngineTypeDef();
            return "I am a car called " . this->GetName() . ", whose " .
                def->GetEngineTypeName() . " engine can run at " .
                def->GetEngineTypeMaxRPM() . " RPM!";
        }
    
    }
    

    那么,那里有名字吗?

6 个答案:

答案 0 :(得分:2)

SingletonRegistry

信不信由你。我今天早上想的是同样的事情。

之前我使用过这种模式,但我从来没有找到它的参考,也不知道如何命名。

我认为是一种“Keyed”单例,其中实例存储在某处,并且使用密钥获取它们。

我最后一次使用它是从不同来源检索数据。

我有大约50个数据库表(使其成为10)并且我有一个前端“表”,其中显示数据,但数据可能来自任何这些来源,每个都需要不同的逻辑(查询,连接,键等)

这个前端是“可配置的”,所以我不知道要显示哪些值以及哪些不会显示。

解决方案是将columnName(在前端)作为键,并获取正确的实例以创建正确的查询。

它在开头安装在哈希映射中,之后从数据库表中检索。

代码是这样的:

class DataFetcher {
    abstract Object getData( Object id );
}

class CustomerNameDataFetcher extends DataFetcher {
    Object getData( Object customerId ) { 
        // select name from customer where id = ? 
     }
}

class CompanyAdressDataFetcher extends DataFetcher { 
     Object getData( Object customerId ) { // don't ask why.
          // select name from company , customer where customer.co = company.co and cu = ?  etc.
     }
} 

class ProductColor extends DataFetcher { 
     Object getData( Object x ) { 
     // join from customer to color, to company to season to a bunch of table where id = ? 
}

// And the list goes on.

每个子类使用不同的逻辑。

在运行时,用户配置了它的视图,并选择他想要查看的内容。

当用户选择要查看的列时,我使用列名和Id来获取数据。

在类方法中,DataFetchers都安装在父类中(我不想为此设置一个separeate类)。

class DataFetcher {
    abstract Object getData( Object id );

    private static final Map fetchers = new HashMap();static { 
        fetchers.put("customer.name", new CustomerNameDataFetcher() );
        fetchers.put("company.address", new CompanyAdressDataFetcher () );
        fetchers.put("product.color", new ProductColor () );
        ...
    }
    public static DataFetcher getFetcher( String id ) { 
        return fetchers.get( id );
    }      

}

最后填写前端表我只是这样称呼:

伪代码

 for each row in table 
      for each column in row
          column.text = DataFetcher.getFetcher( column.id ).getData( row.id )
       end
 end
这是这样的吗?或者我误解了你的描述,而我的描述则完全不同。

最后我认为这被称为SingletonRegistry或类似的东西。我(可能)喜欢你,出于必要而创造了这个。机会是这是一种常见的模式。

答案 1 :(得分:2)

之前我使用过类似的模式,最常用的是游戏。我有一个WeaponDefinition和WeaponInstance类(不完全是那些名字)。 WeaponDefinition类(以及各种子类,如果我有不同类型的武器,例如近战与射弹)将负责跟踪该类型武器的全球数据(射速,最大弹药,名称等),并具有所有的逻辑。 WeaponInstance类(和子类)包含触发序列中的当前状态(用于比较火焰速率),当前弹药计数和指针(它可能是您的示例中的一个经理类的关键,但是对于WeaponDefinition来说,这似乎不是模式的要求。 WeaponInstance有一堆用于触发,重新加载等的函数,它们只调用WeaponDefinition实例上的相应方法,并将自身作为参数传递。这意味着WeaponDefinition的东西不会为游戏世界中的每个坦克/士兵/飞机重复,但它们都有自己的弹药计数等。

我不知道它叫什么,我不确定它与你所谈论的完全相同,但我认为它很接近。这绝对有用。

答案 2 :(得分:1)

听起来像GoF Builder,Prototype和对我来说可能是羽量级的组合。

答案 3 :(得分:1)

听起来像是各种各样的Flyweight(许多汽车共享一个WankelEngine)。但这有什么意义呢?大多数汽车都有发动机,但是它们中的许多汽车如何拥有相同的发动机实例?他们不会那么远。或者你是说很多车都有WankelEngine型发动机?更有意义的是。那么“WankelEngine定义对象”的用途是什么?它是一个工厂,正在构建该对象的味道并将它们传递给请求者?如果是这样,它听起来不像一个定义对象,听起来更像是一个工厂,它正在接受要构建的对象的参数并将该对象返回。

我确实在这里看到了一些很好的GoF练习,特别是你正在编写而不是继承(我的Car有一个引擎而不是我的Car的引擎是一个WankelEngine)。我希望我能完全回忆起这句话,但它就像“继承打破封装”和“赞成合成而不是继承”。

我很好奇这个问题解决了什么。我认为你增加了很多复杂性,我没有看到这种复杂性的需要。也许这是我不懂的语言特有的东西。

GoF的人确实讨论将模式组合成更大的模式,MVC尤其是三种其他模式的集合。听起来你已经做过类似的事情了。

答案 4 :(得分:1)

听起来有点像服务定位器,其中你的羽量重量被注册为单身人士。

答案 5 :(得分:-1)

你所拥有的是地图,即字典。通过将多个键映射到一个对象,您只需要有一个独特的扭曲。

为什么是地图:

  • 保持密钥
  • 使用密钥查询某些数据结构中的值。

您可以在以下位置找到实施:

  • STL(包括:地图)
  • Java(import:java.util.Dictionary)