首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >面向对象设计,交互对象

面向对象设计,交互对象
EN

Stack Overflow用户
提问于 2013-11-30 03:18:45
回答 4查看 145关注 0票数 3

这个问题让我想起了迷你涂鸦之神。有几个对象,其中一些可以相互作用并形成新的对象。每个对象自然都有自己的类:水、火、空气等等。这些都继承自同一个基类。例如,水和火对象可以被组合以形成可以在新的组合中使用的灰对象。

问题是找出一种优雅的方法来处理所有可能的组合。最明显但极其不可维护的解决方案是创建一个函数,该函数接受任意两个对象作为参数,并使用一个巨大的切换块来比较类型名,并确定当这两个对象交互时应该返回哪种类型的对象(如果有的话)。combine(a,b)应该始终等于combine(b,a)也很重要。

对于此场景,什么是可维护且高效的设计?

EN

回答 4

Stack Overflow用户

发布于 2013-11-30 03:32:08

我们不得不在游戏中为此编写代码来碰撞物品。我们最终选择了一个存储了一堆委托方法的二维结构。

代码语言:javascript
复制
      | air            |  wind            | fire
air   |combine(air,air)|combine(air,wind) |combine(air,fire)
wind  |                |combine(wind,wind)|combine(wind,fire)
fire  |                |                  |combine(fire,fire)

稍微思考一下,你只需要填充组合矩阵的一半多一点。

你可以(举个例子):

代码语言:javascript
复制
lookup = 
     new Dictionary<
            Tuple<Type, Type>,
            Func<ICombinable, ICombinable, ICombinable>();
lookup.Add(
   Tuple.Create(typeof(Air), typeof(Fire)),
   (air,fire) => return new Explosion());

然后有一个单一的方法:

代码语言:javascript
复制
ICombinable Combine(ICombinable a,ICombinable b)
{
    var typeA = a.GetType();
    var typeB = b.GetType();
    var typeCombo1 = Tuple.Create(typeA,typeB);
    Func<ICombinable,ICombinable,ICombinable> combineFunc;
    if(lookup.TryGetValue(typeCombo1, out combineFunc))
    {
        return combineFunc(a,b);
    }
    var typeCombo2 = Tuple.Create(typeB,typeA);
    if(lookup.TryGetValue(typeCombo2, out combineFunc))
    {
        return combineFunc(b,a);
    }
     //throw?
}
票数 2
EN

Stack Overflow用户

发布于 2013-11-30 03:48:14

所有的游戏对象都已经以某种方式设计好了。它们要么是硬编码的,要么是在运行时从资源中读取的。

这个数据结构可以很容易地存储在Dictionary<Element, Dictionary<Element, Element>>中。

代码语言:javascript
复制
var fire = new FireElement();
var water = new WaterElement();
var steam = new SteamElement();

_allElements = Dictionary<Element, Dictionary<Element,Element>>
{
    new KeyValuePair<Element, Dictionary<Element, Element>>
    {
        Key = fire,
        Value = new KeyValuePair<Element, Element>
        {
            Key = water,
            Value = steam
        }
    },
    new KeyValuePair<Element, Dictionary<Element, Element>>
    {
        Key = water,
        Value = new KeyValuePair<Element, Element>
        {
            Key = fire,
            Value = steam
        }
    }

}

在加载或定义元素时,您可以只复制它们,因为最多只有几百个。为了便于对IMO进行编码,开销是可以忽略的。

_allElements的键包含所有现有的、可组合的元素。_allElements[SomeElement]的值会生成另一个字典,您可以在希望与之组合的元素上访问该字典。

这意味着您可以使用以下代码找到组合的结果元素:

代码语言:javascript
复制
public Element Combine(Element element1, Element element2)
{
    return _allElements[element1][element2];
}

当它被这样调用时:

代码语言:javascript
复制
var resultingElement = Combine(fire, water);

steam,与调用Combine(water, fire)时的结果相同。

未经测试,但我希望这个原则适用。

票数 1
EN

Stack Overflow用户

发布于 2013-11-30 03:24:51

确切地说,这是接口的正确位置。有了它们,你就可以避免大的开关,每个元素类都可以实现自己的行为,与另一个元素类进行交互。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20292174

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档