我需要更改什么才能正确实施 SOLID 设计?
What do I need to change to implement SOLID design correctly?
我正在尝试学习 SOLID 设计,但我认为我犯了一个错误。我认为 IItem
接口在我的 Player
class 中不遵循 Liskov 替换原则 但是,我不知道如何解决这个问题.如果我从 IItem 添加一个新的界面绘图,我将不得不更改 Player 的方法以添加一个案例来处理它。
我希望玩家 class 只需要一种装备方法,因此需要帮助了解我做错了什么以及如何正确地做。
我的界面的简化版本:
interface IItem
{
string Name { get; set; }
int Value { get; set; }
Quality Quality { get; set; }
EquipmentType Type { get; set; }
}
interface IWeapon : IItem
{
}
interface IArmour : IItem
{
int Defence { get; set; }
Slot Slot { get; set; }
}
消费玩家class:
class Player
{
private Dictionary<Slot, IArmour> armour = new Dictionary<Slot, IArmour>();
private IWeapon weapon;
public bool Equip(IItem item)
{
switch (item.Type)
{
case EquipmentType.Armour:
var armour = item as IArmour;
if (this.armour.ContainsKey(armour.Slot))
{
return false;
}
this.armour.Add(armour.Slot, armour);
return true;
case EquipmentType.Weapon:
var weapon = item as IWeapon;
throw new NotImplementedException();
default:
return false;
}
}
}
上下文枚举:
enum Slot
{
Head = 0,
Soulders = 1,
Gloves = 2,
Neck = 3,
RRing = 4,
LRing = 5,
Torso = 6,
Legs = 7,
Boots = 8,
Bracers = 9,
Belt = 10,
}
enum EquipmentType
{
Armour = 0,
Weapon = 1
}
Liskov 替换原则 通常是关于如何定义 classes。如果您编写一个 class 派生自其他 class (或实现某个接口),则想法是有人应该能够使用您的 class 就好像它是那个的实例一样parent class。您的 subclass 可能有 parent class 没有的其他行为(并且有人正在使用您的 class 就好像它是 parent class 当然无法访问它),但是 parent class 的所有行为都应该在 child class.
在您的示例中,这可能意味着定义不适合 Slot
的 MagicalWholeBodyArmor
,因此如果您尝试访问其 Slot
[=60],则会抛出异常=].将 MagicalWholeBodyArmor
视为 IArmor
的人在试图查看它适合哪个插槽时会大吃一惊。
您编写的 SOLID 规则确实有点违反 Open/Closed 原则。 Open/Closed 原则的一个好的经验法则是 "If I change this bit of code, how many other bits of code in other places do I also have to change?"。如果答案是"lots",那可能是因为你违反了Open/Closed原则。
在您的情况下,添加一个新的 EquipmentType
枚举成员意味着您必须在 Player
class 中找到该 switch 语句并添加一个新的案例。
如果只有一个 switch 语句,那还不错。如果您添加了一种新类型的设备,那么您的 Player
class 可能需要升级 无论如何 ,因此修改 switch 语句作为其中的一部分就可以了。尝试以自己的方式构建解决方案将意味着大量抽象却收效甚微。
然而,如果你在很多不同的地方有很多很多的 switch 语句,它们都查看 EquipmentType
,(并根据它做出不同的决定),你需要找到它们并修复它们,那么这是对 Open/Closed 原则的更大违反,这可能表明您需要 re-architect 将所有这些独立的、不同的逻辑位整合到一个地方。
我正在尝试学习 SOLID 设计,但我认为我犯了一个错误。我认为 IItem
接口在我的 Player
class 中不遵循 Liskov 替换原则 但是,我不知道如何解决这个问题.如果我从 IItem 添加一个新的界面绘图,我将不得不更改 Player 的方法以添加一个案例来处理它。
我希望玩家 class 只需要一种装备方法,因此需要帮助了解我做错了什么以及如何正确地做。
我的界面的简化版本:
interface IItem
{
string Name { get; set; }
int Value { get; set; }
Quality Quality { get; set; }
EquipmentType Type { get; set; }
}
interface IWeapon : IItem
{
}
interface IArmour : IItem
{
int Defence { get; set; }
Slot Slot { get; set; }
}
消费玩家class:
class Player
{
private Dictionary<Slot, IArmour> armour = new Dictionary<Slot, IArmour>();
private IWeapon weapon;
public bool Equip(IItem item)
{
switch (item.Type)
{
case EquipmentType.Armour:
var armour = item as IArmour;
if (this.armour.ContainsKey(armour.Slot))
{
return false;
}
this.armour.Add(armour.Slot, armour);
return true;
case EquipmentType.Weapon:
var weapon = item as IWeapon;
throw new NotImplementedException();
default:
return false;
}
}
}
上下文枚举:
enum Slot
{
Head = 0,
Soulders = 1,
Gloves = 2,
Neck = 3,
RRing = 4,
LRing = 5,
Torso = 6,
Legs = 7,
Boots = 8,
Bracers = 9,
Belt = 10,
}
enum EquipmentType
{
Armour = 0,
Weapon = 1
}
Liskov 替换原则 通常是关于如何定义 classes。如果您编写一个 class 派生自其他 class (或实现某个接口),则想法是有人应该能够使用您的 class 就好像它是那个的实例一样parent class。您的 subclass 可能有 parent class 没有的其他行为(并且有人正在使用您的 class 就好像它是 parent class 当然无法访问它),但是 parent class 的所有行为都应该在 child class.
在您的示例中,这可能意味着定义不适合 Slot
的 MagicalWholeBodyArmor
,因此如果您尝试访问其 Slot
[=60],则会抛出异常=].将 MagicalWholeBodyArmor
视为 IArmor
的人在试图查看它适合哪个插槽时会大吃一惊。
您编写的 SOLID 规则确实有点违反 Open/Closed 原则。 Open/Closed 原则的一个好的经验法则是 "If I change this bit of code, how many other bits of code in other places do I also have to change?"。如果答案是"lots",那可能是因为你违反了Open/Closed原则。
在您的情况下,添加一个新的 EquipmentType
枚举成员意味着您必须在 Player
class 中找到该 switch 语句并添加一个新的案例。
如果只有一个 switch 语句,那还不错。如果您添加了一种新类型的设备,那么您的 Player
class 可能需要升级 无论如何 ,因此修改 switch 语句作为其中的一部分就可以了。尝试以自己的方式构建解决方案将意味着大量抽象却收效甚微。
然而,如果你在很多不同的地方有很多很多的 switch 语句,它们都查看 EquipmentType
,(并根据它做出不同的决定),你需要找到它们并修复它们,那么这是对 Open/Closed 原则的更大违反,这可能表明您需要 re-architect 将所有这些独立的、不同的逻辑位整合到一个地方。