C# 关于新特性的开闭原理
关于开闭原则,我有点不明白。假设您已经完成了以下代码:C# 关于新特性的开闭原理,c#,solid-principles,open-closed-principle,C#,Solid Principles,Open Closed Principle,关于开闭原则,我有点不明白。假设您已经完成了以下代码: public abstract class Player { public string Name { get; set; } public int Level { get; set; } } public sealed class Fighter : Player { /* ... */ } public sealed class Warrior : Player { /* ... */ } 这段代码工作得很好,您已经
public abstract class Player
{
public string Name { get; set; }
public int Level { get; set; }
}
public sealed class Fighter : Player { /* ... */ }
public sealed class Warrior : Player { /* ... */ }
这段代码工作得很好,您已经完成了第一个版本,一切都正常。现在你想添加一些功能,比如玩家可以装备戒指。开-关原则是“开-扩,关-改”。如果我不修改这些类,我如何实现我的玩家可以拥有戒指的事实呢?首先想想为什么这种规则可能有用。关闭修改,打开扩展。这对于必须向后兼容的库或代码是有意义的。想想这个例子: 我编写了“BestLibrary”库,它公开了接口:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff();
}
}
但是在下一个版本中,我想根据一个参数来决定要提供什么Goodies
,因此我将界面更改为:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff(GoodiesType type);
}
}
public enum GoodiesType { All, Type1, Type2 }
现在每个使用我的库的人都必须修复他们的代码,因为他们的项目将停止构建。这是制动器打开/关闭的原理。相反,我应该提出另一种方法,如下所示:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff();
Goodies GiveMeGoodStuff(GoodiesType type);
}
}
在这里,我没有修改任何内容。旧代码仍然有效。有人想要随机的糖果
?他们仍然可以得到它。我用额外的方法扩展了GoodStuff
接口。这样,一切都可以编译,人们可以使用新的功能
如果您从事的项目不是库或api,那么我看不出有任何理由遵循这一原则。需求变化,代码也应该随之变化。首先想想为什么这种规则可能有用。关闭修改,打开扩展。这对于必须向后兼容的库或代码是有意义的。想想这个例子: 我编写了“BestLibrary”库,它公开了接口:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff();
}
}
但是在下一个版本中,我想根据一个参数来决定要提供什么Goodies
,因此我将界面更改为:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff(GoodiesType type);
}
}
public enum GoodiesType { All, Type1, Type2 }
现在每个使用我的库的人都必须修复他们的代码,因为他们的项目将停止构建。这是制动器打开/关闭的原理。相反,我应该提出另一种方法,如下所示:
namespace BestLibrary
{
public interface GoodStuff
{
Goodies GiveMeGoodStuff();
Goodies GiveMeGoodStuff(GoodiesType type);
}
}
在这里,我没有修改任何内容。旧代码仍然有效。有人想要随机的糖果
?他们仍然可以得到它。我用额外的方法扩展了GoodStuff
接口。这样,一切都可以编译,人们可以使用新的功能
如果您从事的项目不是库或api,那么我看不出有任何理由遵循这一原则。需求会发生变化,代码也会随之变化。您可以通过添加新的方法和字段来修改类Player
。它可以扩展。但是如果你已经有了一些方法,比如Jump
或Fight
,你想修改它们,那就违反了原则
想象一下,您的类Fighter
具有方法Fight()
,并且只使用徒手:
public Fighter() : Player
{
...
public virtual void Fight()
{
//use bare hands
}
}
如果您想使用棍子战斗(例如),您不应该修改初始方法fight()
,而是添加另一个类,如FighterWithStick:Fighter
,并覆盖方法fight()
:
public FighterWithStick() : Fighter
{
...
public override void Fight()
{
//use stick
}
}
您可以通过添加新方法和字段来修改classPlayer
。它可以扩展。但是如果你已经有了一些方法,比如Jump
或Fight
,你想修改它们,那就违反了原则
想象一下,您的类Fighter
具有方法Fight()
,并且只使用徒手:
public Fighter() : Player
{
...
public virtual void Fight()
{
//use bare hands
}
}
如果您想使用棍子战斗(例如),您不应该修改初始方法fight()
,而是添加另一个类,如FighterWithStick:Fighter
,并覆盖方法fight()
:
public FighterWithStick() : Fighter
{
...
public override void Fight()
{
//use stick
}
}
你可以考虑阅读。这是一个扩展,而不是一个修改,你把播放器类扩展成一个每个孩子默认继承的环。例如,修改是添加一个抽象的方法,每个孩子都应该修改它。你可以考虑阅读。这是一个扩展,而不是一个修改。例如,修改是添加一个抽象方法,该方法应由每个子级实现,这是一个修改。