我目前有以下内容:
public abstract class CharacterClass
{
public abstract Attribute FirstAttributeBonus { get; }
public abstract Attribute SecondAttributeBonus { get; }
protected Attribute[] attributeBonuses; //2 attribute bonuses, which add 10 to the attributes stored in the array.
protected SKill[] majorSkills; //Major skills for class begin at 30.
protected Skill[] minorSkills; //Minor skills for class begin at 15.
protected IDictionary<int, Character> characterList; //List of characters who apply to this class specifically.
public CharacterClass()
{
}
}
考虑到我创建的任何类都将继承这个基类,并且也继承类字段。例如,一个职业可以是战士;另一个可以是战斗法师,等等。
这是正确的方式来执行这样的设计,而有派生构造函数初始化字段?还是在不继承这些字段的情况下编写类更好?
编辑:我忘了说所有的衍生物都是单例的,为了避免混淆,我把Class的名字改成了"CharacterClass"
我假设你指的不是任何类,而是所有游戏对象类?在这种情况下,如果所有游戏对象确实需要这些属性,那么这可能是一个很好的设计。
抽象基类的作用是在那里收集公共代码,以消除子类中的重复。如果所有游戏对象子类都需要这些字段,那么将它们放在基类中是正确的。如果不同的游戏对象子类将它们初始化为不同的值,那么延迟初始化到子类是正确的。
强制初始化这些字段的一种可能性是在基类中提供一个非默认构造函数,要求子类将初始化值作为参数传递给tor。
我想你是指一个构造函数的例子?修改现有的
public CharacterClass()
{
}
变成了
public CharacterClass(Attribute[] attributeBonuses,
SKill[] majorSkills, Skill[] minorSkills)
{
if(attributeBonuses == null || majorSkills == null || minorSkills == null)
throw new ArgumentException("Null values are not allowed");
this.attributeBonuses = attributeBonuses;
this.majorSkills = majorSkills;
this.minorSkills = minorSkills;
}
你绝对需要拿到一本叫做《Head Start Design Pattern》的书。你不需要读整本书:第一章描述了你想要实现的设计模式。
基本上,你希望你的字符类具有调用类的接口,这些类包含你的实现代码,如技能类,属性类和你稍后添加的所有其他类。这样,你就可以添加新的技能和属性类型,你也可以在运行时修改它们。你不希望字符类包含所有可能的实现。对于你想要做的,你想要支持对象组合而不是继承。
花20分钟阅读第一章:http://oreilly.com/catalog/9780596007126/preview
我认为这是气味。这种代码气味甚至有一个名字:God - class。
在我看来,创建一个"母亲"(或上帝)类并不是一个好主意,所有其他类都从那里继承。
我看到在你的基类一些属性,如MajorSkills
。我看到你将有一个类' BattleImage
',你将从这个基类继承,但是,我不认为一个图像有技能。我将创建更具体的基类,仅在存在Is 关系时才继承这些基类。
我不认为保留受保护的抽象字段对所有派生类都是通用的有什么特别的错误,尽管我建议使用Anders给出的解决方案。
我特别不喜欢的部分是IDictionary<int, Character> characterList;
。
我将假设您的Character
在内部有一个CharacterClass
引用,以便您可以在需要时访问详细信息,并且正如它出现的那样,您将在Character
和CharacterClass
之间创建一个循环。似乎你让CharacterClass有太多的责任。我将把保存特定字符类的所有字符的责任移到其他地方。