2

我有单身课程World。(它不需要是单例的,但它在我的项目中是这样定义的。)

然后我有Component接口,然后由ConcreteComponent1ConcreteComponent2实现。这些都实现了一些不错的方法,例如decorateTheWorld.

在某个时候,World实例会遍历它Compontent的所有孩子,并要求他们通过调用它们来装饰自己decorateTheWorld

这种方法的问题是World, 或之外的东西World需要知道任何类型ComponentWorldcan ,因为Component需要在某个时候以某种方式创建实例。

关键是我不想做一些愚蠢的事情,比如 100 行重复的代码,比如

(new ConcreteComponent1())->registerInTheWorld()
(new ConcreteComponent2())->registerInTheWorld()
(new ConcreteComponent3())->registerInTheWorld()

...我不想诉诸反思。

那么,是否有任何设计模式可以自动使注册部分开箱即用?还是我要求不可能?

4

3 回答 3

2

只要组件实现了一个通用接口,你的世界就不必知道具体的组件,只需要知道接口。

请参阅此示例(C#):

public interface IComponent
{
    void decorateTheWorld();
}

public class ComponentA : IComponent
{
    public void decorateTheWorld() { /* ... */ }
}

public class ComponentB : IComponent { /* ... */ }

在您的 World 类中,假设_componentsIComponents 的集合:

foreach(IComponent comp in _components)
    comp.decorateTheWorld();

现在,如果您不想手动“查找”组件,则可以从已加载的程序集中获取所有类型,并找到实现的类型IComponent,然后使用Activator.CreateInstance.

于 2013-05-01T08:47:47.563 回答
1

由于 World 是单例,我建议 World 将持有一组组件,并且那里的构造函数中的任何组件都将在单例中注册。所以单例会在不知道子类型的情况下迭代它们

于 2013-05-01T09:13:59.800 回答
0

当遇到类似问题时,我采用了这种方法,如下所示:

制作所有组件的数组(不作为具体实现)。

Array<Components> componentsAttributeInWorld

然后使用您自己创建的创建方法一次创建一个或多个组件。使用 for 迭代方法一次创建多个

void createObjectType:(String)nameOfConcreteObjectClass AndCount:(int)numberOfObjects {
    for (int i=0; i<numberOfObjects; i++) {
        Component *comp = [[Class getClassWithName:nameOfConcreteObjectClass] new];
        [componentsAttributeInWorld addObject:comp];
    }
}

之后对象位于 Array/List 中,您可以再次使用 foreach 再次迭代它们。在 Objective-C 中,您可以动态测试 Component 到底是哪个类,然后根据需要执行一些特定于该具体实现的特殊方法。在 Java 中,您甚至可以对字符串使用 switch。

…
for (Component *c in componentsAttributeInWorld) {
    if ([c isClass:@"ConcreteComponent1"]) {
        c.color = ccRED;
    else if ([c isClass:@"ConcreteComponent2"]) {
        c.size = ccsize(1,2,1);
    }
}
…

所以你只需要处理数组,然后排序是不相关的(我用它来知道哪个对象是最旧的),然后你可以使用一个可能更快的集合!

于 2013-05-01T09:44:57.903 回答