开闭原理C#:是私有集#x2B;构造函数初始化是一个例子吗?

开闭原理C#:是私有集#x2B;构造函数初始化是一个例子吗?,c#,oop,solid-principles,open-closed-principle,C#,Oop,Solid Principles,Open Closed Principle,我的同事认为以下代码是C#中开闭原则的一个示例: 他给出的理由是:“一旦类被构造,Id属性的值就被关闭以进行修改” 我认为这是一个错误的解释 我的理解是,开放-关闭原则与关闭以进行修改的财产的价值无关 我相信开闭原则只与设计类有关,这样就可以在不修改现有代码的情况下扩展类的行为 i、 e.如果我进入并编辑PrintIdWithText方法,同时在新行上打印Count的值,我将违反原则。因为我正在修改现有的类 为了满足这一原则,我必须设计类,使其可扩展,例如,我可以通过组合注入打印功能 这将允许我

我的同事认为以下代码是C#中开闭原则的一个示例:

他给出的理由是:“一旦类被构造,Id属性的值就被关闭以进行修改”

我认为这是一个错误的解释

我的理解是,开放-关闭原则与关闭以进行修改的财产的价值无关

我相信开闭原则只与设计类有关,这样就可以在不修改现有代码的情况下扩展类的行为

i、 e.如果我进入并编辑
PrintIdWithText
方法,同时在新行上打印
Count
的值,我将违反原则。因为我正在修改现有的类

为了满足这一原则,我必须设计类,使其可扩展,例如,我可以通过组合注入打印功能

这将允许我在以后添加打印功能,在新行上打印
最大值

我对原则的解释正确吗

他的解释不正确吗?

你是对的。 开闭原则与运行时的可变性或属性值无关

开闭原则是关于代码架构的,这样我们就可以在不修改现有工作代码的情况下添加新的行为

我已经重写了你的代码以遵循OCP。在本例中,
MyClass
通过引入新的
IClassPrinter
(在本例中为
FancyClassPrinter
)打开扩展,以打印
Maximum
属性

请记住,不可能使一个类完全关闭,总会有我们无法预见的修改,因此OCP是一个指南而不是目标

对于您的代码来说,这是一个有点做作的示例,对于这样一个简单的程序来说可能有些过分。还要注意,单一责任原则要求我们将印刷责任转移到另一个类别,即使我们不遵循OCP

using System;
using System.Collections.Generic;

public interface IClassPrinter{
  void PrintValue(MyClass myClass);
}

public class NormalClassPrinter: IClassPrinter{
  public void PrintValue(MyClass myClass)
   {
      Console.WriteLine($"The value of the Id property is: {myClass.Id.ToString()}");
   }
}

public class FancyClassPrinter: IClassPrinter{
  public void PrintValue(MyClass myClass)
   {
      Console.WriteLine($"The value of the Id property is: {myClass.Id.ToString()}");
      Console.WriteLine($"The value of the Maximum property is: {myClass.Maximum.ToString()}");
   }
}

public class MyClass
{
   public int Id { get; private set; }

   public int Count{ get; private set; }

   public int Maximum{ get; private set; }

   public MyClass(int id, int count, int maximum)
   {
       Id = id;
       Count = count;
       Maximum = maximum;
   }

   public void PrintValueWithText(IClassPrinter classPrinter)
   {
      classPrinter.PrintValue(this);
   }
}

class MainClass
{
   static public void Main(string[] args)
   {
    MyClass myClass = new MyClass(0,0,0);

    myClass.PrintValueWithText(new NormalClassPrinter());
    myClass.PrintValueWithText(new FancyClassPrinter());

   }
}

你是对的。Workmate错了。构造函数参数+带有公共getter的属性是不可变对象的一个很好的例子(通常是
struct
)。有关固体中“O”的良好示例,请参见,例如,如果需要另一个统计数据(如平均值),会发生什么情况?你必须修改这个类。如果您想“打印”到另一个目标,如文件或流,该怎么办?你必须修改它。这个类是不可变的,但绝对不会关闭以进行修改。事实上,将统计数据与“打印”它们的代码相结合,无论这意味着什么,都会增加修改的需要是的,您的解释是正确的,本例只是创建不可变的数据结构或类,仅此而已,OCP说当你想要扩展这个类的行为时,你不应该修改这个类!我认为你们两人都没有错,你的同事描述了你如何遵循原则的实施,而你描述了原因。你的同事从来没有说过你应该修改现有的类(至少我从你的问题中得到了这一点)。如果这是他的理解,那么他是错的,但他对成员设置了私人设定者这一事实无疑是朝着开放-关闭原则迈出的一步。
using System;
using System.Collections.Generic;

public interface IClassPrinter{
  void PrintValue(MyClass myClass);
}

public class NormalClassPrinter: IClassPrinter{
  public void PrintValue(MyClass myClass)
   {
      Console.WriteLine($"The value of the Id property is: {myClass.Id.ToString()}");
   }
}

public class FancyClassPrinter: IClassPrinter{
  public void PrintValue(MyClass myClass)
   {
      Console.WriteLine($"The value of the Id property is: {myClass.Id.ToString()}");
      Console.WriteLine($"The value of the Maximum property is: {myClass.Maximum.ToString()}");
   }
}

public class MyClass
{
   public int Id { get; private set; }

   public int Count{ get; private set; }

   public int Maximum{ get; private set; }

   public MyClass(int id, int count, int maximum)
   {
       Id = id;
       Count = count;
       Maximum = maximum;
   }

   public void PrintValueWithText(IClassPrinter classPrinter)
   {
      classPrinter.PrintValue(this);
   }
}

class MainClass
{
   static public void Main(string[] args)
   {
    MyClass myClass = new MyClass(0,0,0);

    myClass.PrintValueWithText(new NormalClassPrinter());
    myClass.PrintValueWithText(new FancyClassPrinter());

   }
}