Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 面向对象设计,交互对象_C#_Oop_Design Patterns - Fatal编程技术网

C# 面向对象设计,交互对象

C# 面向对象设计,交互对象,c#,oop,design-patterns,C#,Oop,Design Patterns,这个问题让我想起了小型游戏涂鸦神。存在多个对象,其中一些对象可以相互交互并形成新对象。每个对象自然都是它自己的类:水、火、空气等。这些都继承自同一基类。例如,水和火的物体可以组合成灰烬物体,可以在新的组合中使用 问题在于找到一种优雅的方法来处理所有可能的组合。最明显但却无法维护的解决方案是创建一个函数,该函数将任意两个对象作为参数,并使用一个巨大的开关块来比较类型名,并确定在这两个对象交互时应返回哪种类型的对象(如果有)。联合收割机(a,b)应始终等于联合收割机(b,a),这一点也很重要 对于这

这个问题让我想起了小型游戏涂鸦神。存在多个对象,其中一些对象可以相互交互并形成新对象。每个对象自然都是它自己的类:水、火、空气等。这些都继承自同一基类。例如,水和火的物体可以组合成灰烬物体,可以在新的组合中使用

问题在于找到一种优雅的方法来处理所有可能的组合。最明显但却无法维护的解决方案是创建一个函数,该函数将任意两个对象作为参数,并使用一个巨大的开关块来比较类型名,并确定在这两个对象交互时应返回哪种类型的对象(如果有)。联合收割机(a,b)应始终等于联合收割机(b,a),这一点也很重要


对于这种情况,什么是可维护和高效的设计?

这正是接口的正确位置。使用它们,您可以避免大的切换,每个元素类都可以实现自己与另一个elemt类交互的行为

我建议使用返回一种特定类型的接口,比如说
InteractionOutcome
。您无法避免使用
开关盒
的需要,但您最终会使用不同的工厂为每个“构造”提供更易于维护的东西


希望我能帮忙

我们必须在游戏中使用代码来碰撞物品。我们最终得到了一个二维结构,它存储了一堆委托方法

      | air            |  wind            | fire
air   |combine(air,air)|combine(air,wind) |combine(air,fire)
wind  |                |combine(wind,wind)|combine(wind,fire)
fire  |                |                  |combine(fire,fire)
稍加考虑,您只需要填充组合矩阵的一半以上

您可以(例如):

查找=
新词典<
元组,
Func();
查找。添加(
Tuple.Create(typeof(Air)、typeof(Fire)),
(空气、火)=>返回新爆炸();
然后有一个单一的方法:

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?
}
ICombinable合并(ICombinable a,ICombinable b)
{
var typeA=a.GetType();
var typeB=b.GetType();
var typeCombo1=Tuple.Create(typeA,typeB);
Func-combineFunc;
if(lookup.TryGetValue(typeCombo1,out combineFunc))
{
返回combineFunc(a,b);
}
var typeCombo2=Tuple.Create(typeB,typeA);
if(lookup.TryGetValue(typeCombo2,out combineFunc))
{
返回combineFunc(b,a);
}
//扔?
}

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

此数据结构可以很容易地存储在
字典中

当被称为:

var resultingElement = Combine(fire, water);
产生
蒸汽
,与
联合收割机(水、火)
调用的结果相同


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

最好的方法是使用设计模式。查看创建的创建类型和行为类型。您可以使用查找表,将两个objectId(例如“火”、“水”)传递给它,并使用一个覆盖了equals的对象作为键。您可以这样做:var key=newidset(doodle1.Name,doodle2.Name);字符串结果=可查找[键];使用给定的结果,可以创建结果对象。在我看来,每个对象都有一个类,我宁愿有一个普通的类,因为我怀疑涂鸦除了设置一些参数之外,是否真的有任何特殊功能。这是一个非常多的接口。关系的另一端呢。如果你将(例如)空中和火力结合起来,谁对结果负责,或者他们都实施了“组合器”(导致冗余)?这应该可以做到,谢谢。最好是返回null,而不是抛出,因为某些对象没有组合。
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
        }
    }

}
public Element Combine(Element element1, Element element2)
{
    return _allElements[element1][element2];
}
var resultingElement = Combine(fire, water);