• C#高级--设计模式(七个原则)


    一、单一职责原则

    原理:

    单一职责原则即:对于一个类而言,应该仅有一个引起他变化的原因。换言之,一个类只负责一个功能领域中的相应职责。

    单一职责原则是实现高内聚、低耦合的指导方针,它是最简单但又最难运用的原则,其难点和重点在于发现职责,并把这些职责相互分离,即区分职责的粒度问题

    总而言之,就是一个类中,只负责一件事,只有一个引起变更的原因。

    单一职责的好处是:

    好处一:提高代码的可读性,提高系统的可维护性

    好处二:降低类的复杂度,一个模块只负责一个职责,提高系统的可拓展性和可维护性。

    好处三:降低变更引起的风险。变更是必然的。如果单一职责做的更好,当修改一个功能的时候可以显著降低对另一个功能的影响。

    二、开放封闭原则

    原理:

    1、对扩展开放,对修改关闭。其目的即:提高代码可复用性和可维护性。 尽量少地去改动已有的模块,尤其是底层模块。

    2、在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级,可以通过使用接口和抽象类达到这样的效果。

    其精神所在即:面向需求,对程序的改动是通过添加新代码进行的而不是更改现有代码。 不更改抽象层而可修改系统实现层。

    三、里氏替换原则

    原理:

    1、任何基类可以出现的地方,子类一定可以出现,即:子类型必须能够替换掉其父类型。

    2、LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。

    3、LSP是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范

    四、依赖倒置原则

    原理:

    1.高层模块不应该依赖于低层模块,两者都应以来抽象;

    2.抽象不应该依赖于细节,细节应该依赖与抽象。

     简单的说就是要求对抽象进行编程,不要对实现进行编程,这里的抽象即抽象类和接口。

    依赖倒置原则的本质就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,互不影响,

    实现模块间的松耦合。 

    关于依赖

     1、⼀一个优秀的⾯面向对象程序设计,核⼼心的原则之⼀一就是将变化「隔离」/「封装」,
    使得变化部分发⽣生变化时,其他部分,不不受影响。
    2、为了了实现这个⽬目的,需要使⽤用⾯面向接⼝口编程,使⽤用后,客户类,不不再直接依赖服务类,
    ⽽而是依赖⼀一个抽象的接⼝口,这样,客户类就不不能在内部直接实例例化服务类。
    3、但是客户类在运⾏行行的过程中,⼜又需要具体的服务类来提供服务,因为接⼝口是不不能实例例化的,
    就产⽣生了了⼀一个⽭矛盾:客户类不不允许实例例化服务类,但是客户类⼜又需要服务类的服务。
    4、为了了解决这个⽭矛盾,我们设计了了⼀一种解决⽅方案,既:客户类定义⼀一个注⼊入点,⽤用于服务类的注⼊入,
    ⽽而客户类的客户类(Program类)负责根据情况,实例例化服务类,注⼊入到客户类中,从⽽而解决了了这个⽭矛盾。

    依赖倒置代码案例如下所示:

    1. namespace Program_依赖倒置原则
    2. {
    3. internal class Program
    4. {
    5. static void Main(string[] args)
    6. {
    7. //歌手歌唱不同国家的歌曲
    8. Singer singer = new Singer();
    9. singer.SingSongChinese(new ChinenseSong());
    10. singer.SingSongChinese(new JapaneseSong());
    11. Console.ReadKey();
    12. }
    13. }
    14. interface ISong
    15. {
    16. string SingSong();
    17. }
    18. class ChinenseSong:ISong
    19. {
    20. public string SingSong()
    21. {
    22. return "我在唱中文歌";
    23. }
    24. }
    25. class KoreaSong : ISong
    26. {
    27. public string SingSong()
    28. {
    29. return "韩国歌曲";
    30. }
    31. }
    32. class JapaneseSong : ISong
    33. {
    34. public string SingSong()
    35. {
    36. return "日本歌曲";
    37. }
    38. }
    39. class Singer
    40. {
    41. //调用者和被调用者之间是强耦合的关系
    42. //使用抽象封装变化
    43. // 通过抽象,使各个模块或者类的实现彼此独立,互不影响,实现模块间的松耦合
    44. public void SingSongChinese(ISong cs)
    45. {
    46. Console.WriteLine("正在唱"+cs.SingSong());
    47. }
    48. }
    49. }

     

    五、接口隔离原则

    原理:

    1、客户端不应该依赖他不需要的接口。

    2、一个类对另一个类的依赖应该建立在最小接口上

    3、接口尽量细分不要一个接口中放多种方法。

    它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。

    代码案例: 

    1. namespace Program_接口分离原则
    2. {
    3. internal class Program
    4. {
    5. static void Main(string[] args)
    6. {
    7. }
    8. }
    9. interface IScore
    10. {
    11. //修改某个学生的成绩
    12. void ChangeScore();
    13. }
    14. //接口要符合高内聚
    15. //接口要符合单一职责原则
    16. //还要实现类权限的问题,对接口中的方法进行分类细分
    17. interface ISuperScore
    18. {
    19. void AddScore();
    20. //删除某个学生的成绩
    21. void DeleteScore();
    22. }
    23. interface IQueryScore
    24. {
    25. void QueryScore();
    26. }
    27. class Teacher:IScore,IQueryScore
    28. {
    29. public void AddScore() { }
    30. public void DeleteScore() { }
    31. public void QueryScore() { }
    32. public void ChangeScore()
    33. {
    34. }
    35. }
    36. class Student : IQueryScore
    37. {
    38. public void QueryScore()
    39. {
    40. throw new NotImplementedException();
    41. }
    42. }
    43. }

    六、迪米特原则

    原理:

    1、它要求一个对象对其他对象有最少的了解(最少知识原则)。

    2、降低类之间的耦合、

    3、迪米特法则实际上是一个类在创建方法和属性时要遵守的法则。

    迪米特法则强调,在类的结构设计上,尽量降低成员的访问权限。

    其根本思想即强调了类之间的松耦合。 一般来说,类之间的耦合越弱,越有利于复用,一个处于弱耦合的类被修改,不会对关系类造成波及。

    案例打印总公司员工和分公司员工信息: 

    1. namespace Program_迪米特原则
    2. {
    3. internal class Program
    4. {
    5. static void Main(string[] args)
    6. {
    7. //总公司员工类:ID
    8. //总公司员工管理类
    9. //添加总公司员工
    10. //打印总公司每个员工
    11. //打印分公司每个员工
    12. //分公司员工类
    13. //分公司管理类
    14. HeadEmployeeManager headEmployeeManager = new HeadEmployeeManager();
    15. headEmployeeManager.PrintEmployee();
    16. Console.ReadKey();
    17. }
    18. class HeadEmployee
    19. {
    20. public int ID { get; set; }
    21. }
    22. class HeadEmployeeManager
    23. {
    24. //总公司员工集合
    25. private List headEmployee = new List();
    26. //添加总公司员工
    27. public List AddHeadEmployees()
    28. {
    29. for(int i = 0; i < 10; i++)
    30. {
    31. headEmployee.Add(new HeadEmployee { ID = i+1 });
    32. }
    33. return headEmployee;
    34. }
    35. public void PrintEmployee()
    36. {
    37. this.AddHeadEmployees();
    38. //打印总公司员工
    39. Console.WriteLine("===========================以下是总公司员工的编号==========================");
    40. for (int i = 0;i
    41. {
    42. Console.WriteLine(headEmployee[i].ID);
    43. }
    44. Console.WriteLine("==========================以下是分公司员工的编号============================");
    45. //打印分公司员工
    46. //创建分公司员工管理类的对象
    47. BodyEmployeeManager bodyEmployeeManager = new BodyEmployeeManager();
    48. //调用AddBodyEmployee添加分公司成员,并获取返回值
    49. List listBodyEmployees = bodyEmployeeManager.AddBodyEmployees();
    50. for(int i = 0; i < listBodyEmployees.Count;i++)
    51. {
    52. Console.WriteLine(listBodyEmployees[i].ID);
    53. }
    54. }
    55. }
    56. //分公司
    57. class BodyEmployee
    58. {
    59. public int ID { get; set; }
    60. }
    61. class BodyEmployeeManager
    62. {
    63. private List bodyEmployees = new List();
    64. public List AddBodyEmployees()
    65. {
    66. for(int i = 0; i < 5; i++)
    67. {
    68. bodyEmployees.Add(new BodyEmployee { ID = i+1 });
    69. }
    70. return bodyEmployees;
    71. }
    72. }
    73. }
    74. }

    七、合成复用原则

    原理:

    1.合成复用原则,又称为组合聚合复用原则。

    2.尽量使用对象组合,而不是继承来达到复用。

    3.合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承。

    继承带来的问题: 

    1.破坏了系统的封装性,基类发生了改变,子类的实现也会发生改变。

    2.子类如果不需要Method3,则系统的耦合性变高。

    3.继承使静态的不能在程序运行时发生改变。

    合成复用具体情况实施代码: 

    1. namespace Program_复合复用原则
    2. {
    3. internal class Program
    4. {
    5. static void Main(string[] args)
    6. {
    7. //继承问题:
    8. //可能造成子类泛滥
    9. //可能会造成子类数量爆炸
    10. //打破了类的封装性
    11. //创建油车对象
    12. GasCar gascar = new GasCar(new RedColor());
    13. gascar.Move();
    14. Console.ReadKey();
    15. }
    16. }
    17. interface IColor
    18. {
    19. string GetColor();
    20. }
    21. class WhiteColor : IColor
    22. {
    23. public string GetColor()
    24. {
    25. return "我是白色的汽车";
    26. }
    27. }
    28. class BlackColor : IColor
    29. {
    30. public string GetColor()
    31. {
    32. return "我是黑色的汽车";
    33. }
    34. }
    35. class RedColor : IColor
    36. {
    37. public string GetColor()
    38. {
    39. return "我是红色的汽车";
    40. }
    41. }
    42. abstract class Car
    43. {
    44. public IColor color { get; set; }
    45. public Car(IColor Color)//组合,强拥有关系
    46. {
    47. this.color = Color;
    48. }
    49. public abstract void Move();
    50. }
    51. class GasCar : Car
    52. {
    53. public GasCar(IColor color) : base(color)
    54. {
    55. }
    56. public override void Move()
    57. {
    58. Console.WriteLine(this.color.GetColor()+"的电动汽车");
    59. }
    60. }
    61. class ElectricCar : Car
    62. {
    63. public ElectricCar(IColor Color) : base(Color)
    64. {
    65. }
    66. public override void Move()
    67. {
    68. Console.WriteLine(this.color.GetColor()+"的汽油汽车");
    69. }
    70. }
    71. }

    八、设计原则总结

  • 相关阅读:
    H3C S5560 交换机配置管理地址
    如何定位线上CPU占用过高的问题
    Dubbo面试题(二)
    【Qt进阶之自定义控件】使用QListWidget实现自定义Item效果
    SolVES4.1学习2——导入数据运行模型
    java计算机毕业设计人才库构建研究源码+系统+mysql数据库+lw文档
    【C++笔试强训】第二十一天
    Shell入门2
    天软特色因子看板 (2023.08 第08期)
    Zookeeper
  • 原文地址:https://blog.csdn.net/qq_53631431/article/details/136286185