标签: solid-principles

单一责任原则(SRP)和我的RPG的类结构看起来"怪异"

我正在制作角色扮演游戏,只是为了好玩,并了解有关SOLID原则的更多信息.我关注的第一件事就是SRP.我有一个"角色"类,代表游戏中的角色.它有Name,Health,Mana,AbilityScores等等.

现在,通常我也会在我的Character类中放置方法,所以它看起来像这样......

   public class Character
   {
      public string Name { get; set; }
      public int Health { get; set; }
      public int Mana { get; set; }
      public Dictionary<AbilityScoreEnum, int>AbilityScores { get; set; }

      // base attack bonus depends on character level, attribute bonuses, etc
      public static void GetBaseAttackBonus();  
      public static int RollDamage();
      public static TakeDamage(int amount);
   }
Run Code Online (Sandbox Code Playgroud)

但是由于SRP,我决定将所有方法都移到一个单独的类中.我将该类命名为"CharacterActions",现在方法签名看起来像这样......

public class CharacterActions
{
    public static void GetBaseAttackBonus(Character character);
    public static int RollDamage(Character character);
    public static TakeDamage(Character character, int amount);
} …
Run Code Online (Sandbox Code Playgroud)

c# design-patterns solid-principles

13
推荐指数
2
解决办法
2573
查看次数

IoC:连接事件处理程序的依赖项

我正在构建一个WinForms应用程序,其UI只包含一个NotifyIcon动态填充的UI ContextMenuStrip.有一个MainForm共同持有的申请,但这是从来没有看见.

我开始尽可能安全地构建它(使用Autofac来处理对象图)并且对我的成功感到非常满意,即使使用O部分也相当不错.随着我目前正在实施的扩展,似乎我发现了我的设计中的一个缺陷,需要重新改造一下; 我想知道我需要去的方式但是有点不清楚如何准确定义依赖关系.

如上所述,菜单部分在启动应用程序后动态填充.为此,我定义了一个IToolStripPopulator接口:

public interface IToolStripPopulator
{
    System.Windows.Forms.ToolStrip PopulateToolStrip(System.Windows.Forms.ToolStrip toolstrip, EventHandler itemclick);
}
Run Code Online (Sandbox Code Playgroud)

将此实现注入到MainForm,并且Load()方法PopulateToolStrip()使用ContextMenuStrip表单中定义的处理程序调用.populator的依赖关系仅与获取用于菜单项的数据有关.

这个抽象通过一些进化步骤很好地工作,但是当我需要多个事件处理程序时,这已经不够了,例如因为我正在创建几个不同的菜单项组 - 仍然隐藏在单个IToolStripPopulator界面后面,因为表单不应该是完全关心这一点.

正如我所说,我想我知道一般结构应该是什么样的 - 我将IToolStripPopulator接口重命名为更具体的东西*并创建了一个新PopulateToolStrip()方法,其方法不接受EventHandler参数,而是将其注入到对象中(也允许更多关于实现所需的处理程序数量的更多灵活性等).这样,我的"最重要的" IToolStripPopulator可以很容易地成为任何数量的特定适配器的适配器.

现在我不清楚的是我应该如何解决EventHandler依赖项.我认为处理程序应该全部定义MainForm,因为它具有正确响应菜单事件所需的所有其他依赖项,并且它还"拥有"菜单.这意味着我IToolStripPopulator最终注入到MainForm中的MainForm对象的依赖关系需要依赖于对象本身Lazy<T>.

我的第一个想法是定义一个IClickHandlerSource接口:

public interface IClickHandlerSource
{
    EventHandler GetClickHandler();
}
Run Code Online (Sandbox Code Playgroud)

这是由我实现的MainForm,我的具体IToolStripPopulator实现依赖于Lazy<IClickHandlerSource>.虽然这有效,但它是不灵活的.我要么必须为可能越来越多的处理程序定义单独的接口(严重违反OCP与MainForm类)或不断扩展IClickHandlerSource(主要违反ISP).直接依赖事件处理程序在消费者方面看起来是一个好主意,但是通过惰性实例(或类似)的属性单独连接构造函数似乎非常混乱 - 如果可能的话.

我最好的打赌似乎是这样的: …

c# dependency-injection inversion-of-control winforms solid-principles

13
推荐指数
1
解决办法
2052
查看次数

C的SOLID原则实现

我知道SOLID原则是针对面向对象语言编写的.

我在书中找到了罗伯特·马丁的"嵌入式C的测试驱动开发",本书最后一章的后续句子:

"应用开放封闭原则和Liskov替代原则可以实现更灵活的设计."

由于这是一本C(无c ++或c#)的书,应该有一种方法来实现这个原则.

在C中实现这个原则有什么标准方法吗?

c c++ design-principles solid-principles c++11

13
推荐指数
2
解决办法
4687
查看次数

liskov替换原理与界面隔离原理的区别

Liskov 替换原则 (LSP) 和接口隔离原则 (ISP) 之间有什么核心区别吗?最终,两者都保证设计具有通用功能的界面,并在您具有特殊功能时引入新界面。

liskov-substitution-principle interface solid-principles interface-segregation-principle

13
推荐指数
3
解决办法
3951
查看次数

如何在MVVM中构建ViewModel而不违反单一责任原则?

罗伯特马丁说:"一个班级改变的理由永远不应该超过一个".

让我们考虑绑定到View的ViewModel类.ViewModel可能(甚至可能)由彼此不相关的属性组成.对于小视图,ViewModel可能非常一致,但是当应用程序变得更加复杂时,ViewModel将公开可能因不同和无关原因而发生变化的数据.

我们是否应该在ViewModel类的情况下担心SRP原则?

silverlight wpf mvvm solid-principles

12
推荐指数
1
解决办法
1660
查看次数

string.IsNullOrEmpty(myString)或string.IsNullOrWhiteSpace(myString)是否违反了SRP规则?

如问题所示,

由于我们使用像IsNullOrEmpty或IsNullOrWhiteSpace这样的字符串函数作为函数显示的名称,这些函数执行多个作业,是不是违反了SRP

相反,它不应该是string.isValid(Enum typeofValidation)而不是使用策略模式来选择正确的策略进行验证.

或者在实用程序类或静态类中违反SRP是完全可以的.

c# single-responsibility-principle solid-principles

12
推荐指数
1
解决办法
609
查看次数

实施多个接口是否违反单一责任原则?

来自维基百科:

单一责任原则规定每个班级应该承担一项责任,并且该责任应完全由班级封装.

这是否意味着实现多个接口违反了这一原则?

language-agnostic oop single-responsibility-principle multiple-inheritance solid-principles

12
推荐指数
1
解决办法
1327
查看次数

C#中重用的抽象原则

在我们的C#MVC应用程序中,我们有很多接口,它们将实现它们的对象映射为1到1.即:基本上,对于创建的每个对象,已经执行了"提取界面"操作.

Moq使用这些接口为我们的单元测试生成模拟对象.但这是接口重复使用的唯一时间.

我们系统中没有具体对象实现多个接口.

谁能告诉我这是否会导致问题在路上?如果是这样,他们会是什么?

我在想,我们的应用程序有很多重复,例如在这两个接口(编辑:在我们的服务层)中,唯一不同的是方法名称和它们所采用的参数类型,但在语义上他们做与他们发送消息的存储库相同:

interface ICustomer
{
    void AddCustomer(Customer toAdd);
    void UpdateCustomer(Customer toUpdate);
    Customer GetById(int customerId);
}

interface IEmployee
{
    void AddEmployee(Employee toBeAdded);
    void UpdateEmployee(Employee toUpdate);
    Employee GetById(int employeeId);       
}
Run Code Online (Sandbox Code Playgroud)

这就是我认为重用的抽象原则会出现的地方,即将代码转换为类似的东西:

public interface IEmployee: IAdd<Employee>, IUpdate<Employee>, IFinder<Employee>
Run Code Online (Sandbox Code Playgroud)

这与存储库模式无关 - 这是关于任何层中的接口,看起来它们共享语义相同的行为.是否值得为这些操作派生通用接口并使"子接口"继承它们?

至少它会保持方法的签名一致.但这会给我带来什么其他好处呢?(除了利斯科夫替代原则)

现在,方法的名称和返回类型都到处都是.

我读过Mark Seemann关于Reused抽象原理的博客,但我不明白,坦白说.也许我只是愚蠢:)我还阅读了Fowler对Header Interfaces的定义.

c# oop abstraction solid-principles

12
推荐指数
2
解决办法
1110
查看次数

覆盖虚拟布尔纯方法而不破坏LSP

例如,我们有以下结构:

class Base
{
    [pure]
    public virtual bool IsValid(/*you can add some parameters here*/)
    {
       //body
    }
}

class Child : Base
{
    public override bool IsValid(/*you can add some parameters here*/)
    {
       //body
    }
}
Run Code Online (Sandbox Code Playgroud)

你能否填写Base::IsValid()Child::IsValid()与不同的机构,但没有与LSP的冲突?让我们想象它只是分析的方法,我们无法改变实例的状态.我们能做到吗?我对任何一个例子感兴趣.在一般情况下,我试图了解虚拟(身体)布尔方法是否是反模式.

oop design-patterns liskov-substitution-principle solid-principles

12
推荐指数
1
解决办法
268
查看次数

真实世界的Opensource c#应用程序显示了良好的代码

我一直在阅读SOLID原则,并想知道在DOTNET中是否有一个很好的大型开源应用程序或项目,它显示了在现实世界产品中使用的SOLID原则.

如果有任何其他开源项目被认为是良好的编码样本,我也很想看到它们.

c# open-source solid-principles

11
推荐指数
1
解决办法
1051
查看次数