zoukankan      html  css  js  c++  java
  • 六大原则

    六大设计模式原则

    1. 单一职责原则(Single Responsibility Principle)
    2. 里氏替换原则(Liskov Substitution Principle)
    3. 依赖倒置原则(Dependence Inversion Principle)
    4. 接口隔离原则(Interface Segregation Principle)
    5. 迪米特法则 (Law Of Demeter)
    6. 开闭原则 (Open Closed Principle)

    设计模式:面向对象语言开发过程中,遇到种种的场景和问题,提出的解决方案和思路,沉淀下来设计模式是解决具体问题的套路

    设计模式六大原则:面向对象语言开发过程中,推荐的一些指导性原则没有明确的招数,而且也经常会被忽视/违背

    一,单一职责原则(Single Responsibility Principle)

    单一职责原则:类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,有可能会导致原本运行正常的职责P2功能发生故障。一个类只负责一件事儿。面向对象语言开发,类是一个基本单位,单一职责原则就是封装的粒度。写分支判断,然后执行不同的逻辑,其实这就违背了单一职责原则,但是功能是可以实现的。

    举例说明:

     1 /// <summary>
     2     /// 封装
     3     /// 动物类
     4     /// 简单意味着稳定
     5     /// </summary>
     6     public class Animal
     7     {
     8         private string _Name = null;
     9         public Animal(string name)
    10         {
    11             this._Name = name;
    12         }
    13         /// <summary>
    14         /// 这个方法就挺不稳定,经常各种分支变化经常修改
    15         /// </summary>
    16         public void Breath()
    17         {
    18             if (this._Name.Equals(""))
    19                 Console.WriteLine($"{this._Name} 呼吸空气");
    20             else if (this._Name.Equals(""))
    21                 Console.WriteLine($"{this._Name} 呼吸空气");
    22             else if (this._Name.Equals(""))
    23                 Console.WriteLine($"{this._Name} 呼吸水");
    24             else if (this._Name.Equals("蚯蚓"))
    25                 Console.WriteLine($"{this._Name} 呼吸泥土");
    26         }
    27         //BreathChicken  BreathFish
    28 
    29         //应该拆分了
    30         public void Action()
    31         {
    32             if (this._Name.Equals(""))
    33                 Console.WriteLine($"{this._Name} flying");
    34             else if (this._Name.Equals(""))
    35                 Console.WriteLine($"{this._Name} walking");
    36             else if (this._Name.Equals(""))
    37                 Console.WriteLine($"{this._Name} Swimming");
    38             else if (this._Name.Equals("蚯蚓"))
    39                 Console.WriteLine($"{this._Name} Crawling");
    40         }
    41     }

    我们声明一个动物,但是每个动物的action是不一样的,顺着我们的思维模式,我们会在action中增加对应的if来判断,不同的动物有不同的动作,

    类似于这样的,在一个方法中写分支判断,然后执行不同的逻辑,这就违背了单一职责原则,但是其实我们想要的功能完全能实现,如果种类比较少且不变的情况下,我们完全可以这样操作,但是如果种类比较多且经常容易发生改变,那我们这样写就有很大的隐患,因为其中的改变有可能会影响到其它的。

    我们可以对其进行改变,比如我们可以先创建一个基类:

     public abstract class AbstractAnimal
        {
            protected string _Name = null;
            public AbstractAnimal(string name)
            {
                this._Name = name;
            }
    
            public abstract void Breath();//呼吸的方法
            public abstract void Action();//执行的动作
        }

    然后可以创建不同动物的类来继承于这个基类:

    public class Chicken : AbstractAnimal
        {
            public Chicken(string name) : base(name)
            {
            }
    
            public Chicken() : base("")
            {
            }
    
            public override void Breath()
            {
                Console.WriteLine($"{base._Name} 呼吸空气");
            }
            public override void Action()
            {
                Console.WriteLine($"{base._Name} flying");
            }
        }
     public class Fish : AbstractAnimal
        {
            public Fish() : base("")
            {
            }
    
            public override void Breath()
            {
                Console.WriteLine($"{base._Name} 呼吸水");
            }
            public override void Action()
            {
                Console.WriteLine($"{base._Name} swimming");
            }
        }

    类似于上面的这两个类,每个类中实现自己的方法,一个类只负责自己的事情,且都比较单一,简单意味着稳定,意味着强大,这就是所谓的单一职责原则,那么究竟什么时候回使用单一职责原则呢?如果类型复杂,方法多,这样建议使用单一职责原则!

    使用单一职责原则有自己的利弊:

    1.拆分成父类+子类 每个类很简单,简单意味着稳定 意味着强大。

    2. 拆分后,也会造成代码量的增加。

    3.类多了,使用成本也高(理解成本)。与没有拆分前 都是放在一个类或者方法中实现,只用关注一个类;而拆分后,需要关注的类变多了,需要理解每个类的内容才能方便使用。

    单一职责分为以下五种:

    方法级别的单一职责原则:一个方法只负责一件事儿(职责分拆小方法,分支逻辑分拆)。
    类级别的单一职责原则:一个类只负责一件事儿。
    类库级别的单一职责原则:一个类库应该职责清晰。
    项目级别的单一职责原则:一个项目应该职责清晰(客户端/管理后台/后台服务/定时任务/分布式引擎)。
    系统级别的单一职责原则:为通用功能拆分系统(IP定位/日志/在线统计)。

    二. 里氏替换原则(Liskov Substitution Principle)

    任何使用基类的地方,都可以透明的使用其子类,这主要是指 继承+透明(安全,不会出现行为不一致)

    继承:子类拥有父类的一切属性和行为,任何父类出现的地方,都可以用子类来代替,主要是因为:

    1:父类有的,子类是必须有的(私有不继承);如果出现了子类没有的东西,那么就应该断掉继承;、

    2:子类可以有自己的属性和行为,但是子类出现的地方,父类不一定能代替

    3:父类实现的东西,子类就不要再写了,(就是不要new隐藏),如果想修改父类的行为,通过abstract/virtual

    举例:

     public class People
        {
            public int Id { get; set; }
            public string Name { get; set; }
    
            //abstract void Eat();
            public void Traditional()
            {
                Console.WriteLine("仁义礼智信 温良恭俭让 ");
            }
        }
    
        public class Chinese : People
        {
            public string Kuaizi { get; set; }
            public void SayHi()
            {
                Console.WriteLine("早上好,吃了吗?");
            }
    
        }
    
        public class Hubei : Chinese
        {
            public string Majiang { get; set; }
            public new void SayHi()
            {
                Console.WriteLine("早上好,过早了么?");
            }
        }
    
        

    调用:

                {
                    //People people = new Chinese();
                    Chinese people = new Chinese();
                    people.Traditional();
                    people.SayHi();
                }
                {
                    Chinese people = new Hubei();
                    people.Traditional();
                    people.SayHi();
    
                }
                {
                    var people = new Hubei();
                    people.Traditional();
                    people.SayHi();
                }

    比如:现在有个日本人 ,日本人是没有传统的,但是日本人是人。如果日本人也继承people类;

    
    
     1   public class Japanese : People
     2     {
     3         //public int Id { get; set; }
     4         //public string Name { get; set; }
     5         //public new void Traditional()
     6         //{
     7         //    Console.WriteLine("忍者精神 ");
     8         //throw new Exception();
     9         //}
    10         //Traditional也会继承 但是Japanese又没有Traditional
    11         public void Ninja()
    12         {
    13             Console.WriteLine("忍者精神 ");
    14         }
    15 
    16     }
    
    

    可以通过抛出异常的方式解决 日本人没有传统这个方法,或者是新建一个类,日本人继承新的类,或者是在方法前加 new 关键字来隐藏 public new void Traditional();

      public class Animal//让日本人继承自Animal
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }

      

     
     1  public class Japanese : Animal
     2     {
     3         public int Id { get; set; }
     4         public string Name { get; set; }
     5         public new void Traditional()
     6         {
     7             Console.WriteLine("忍者精神 ");
     8             throw new Exception();
     9         }
    10         //Traditional也会继承 但是Japanese又没有Traditional
    11         public void Ninja()
    12         {
    13             Console.WriteLine("忍者精神 ");
    14         }
    15 
    16     }

     注意的是:如果是普通的方法,以左边为主,就是左边是什么类,就调用谁的普通方法(编译时决定),如果是abstract或者virtual则是以右边为主(运行时决定),所以:父类有的方法,子类就不要再写了,(就是不要new隐藏),如果想修改父类的方法,通过abstract/virtual来标识!

    三,迪米特法则 Law Of Demeter

    迪米特法则:最少知道原则,一个对象应该对其他对象保持最少的了解。只与直接的朋友通信。

    举例:

     1  /// <summary>
     2     /// 学校
     3     /// </summary>
     4     public class School
     5     {
     6         public int Id { get; set; }
     7         public string SchoolName { get; set; }
     8         public List<Class> ClassList { get; set; }
     9 
    10         public void Manage()
    11         {
    12             Console.WriteLine("Manage {0}", this.GetType().Name);
    13             foreach (Class c in this.ClassList)
    14             {
    15               
    16                 c.ManageClass();//1 遵循了迪米特
    17                 //List<Student> studentList = c.StudentList;
    18                 //foreach (Student s in studentList)
    19                 //{
    20                 //    Console.WriteLine(" {0}Manage {1} ", s.GetType().Name, s.StudentName);
    21                 //}//2 违背了迪米特法则
    22 
    23             }
    24         }
    25 
    26 
    27     }


     1  /// <summary>
     2     /// 班级
     3     /// </summary>
     4     public class Class
     5     {
     6         public int Id { get; set; }
     7         public string ClassName { get; set; }
     8 
     9         public List<Student> StudentList { get; set; }
    10 
    11 
    12         public void ManageClass()
    13         {
    14             Console.WriteLine(" {0}Manage {1} ", this.GetType().Name, this.ClassName);
    15             foreach (Student s in this.StudentList)
    16             {
    17                 s.ManageStudent();
    18                 //Console.WriteLine(" {0}Manage {1} ", s.GetType().Name, s.StudentName);
    19             }
    20 
    21         }
    22 
    23 
    24     }
     1   /// <summary>
     2     /// 学生
     3     /// </summary>
     4     public class Student
     5     {
     6         public int Id { get; set; }
     7         public string StudentName { get; set; }
     8         public int Height { private get; set; }
     9 
    10         public int Salay;
    11 
    12         public void ManageStudent()
    13         {
    14             Console.WriteLine(" {0}Manage {1} ", this.GetType().Name, this.StudentName);
    15         }
    16


     类与类之间的关系: 

     纵向:继承≈实现(最密切)

     横向:聚合> 组合> 关联> 依赖(出现在方法内部)
     高内聚低耦合
     迪米特法则,降低类与类之间的耦合 只与直接的朋友通信,就是要尽量避免依赖更多类型  基类库(BCL--框架内置的)的类型除外
     迪米特,也会增加一些成本,工作中有时候会去造一个中介/中间层,门面模式 中介者模式 分层封装 
     
     项目中应用场景:上层UI下订单---订单系统&支付系统&仓储&物流  门面模式--上层交互门面--门面依赖子系统  三层架构:UI---BLL---DAL
     去掉内部依赖
     降低访问修饰符权限
     private
     protected
     internal
     protected internal 子类或者同类库
     public

     迪米特,依赖别人更少,让别人了解更少

     
  • 相关阅读:
    从Delegate.CreateDelegate看值类型的实例方法
    c#编译器如何处理匿名委托
    线程静态的几个特点
    Framework 3.5学习笔记
    看看给我用的基类,还有多少人愿意做下去
    .net里面数组的复制
    装饰模式与大接口的装饰模式的思考
    SingleTon的实现与性能
    特性与方法注入
    CLR与浮点数
  • 原文地址:https://www.cnblogs.com/super-xi-xi/p/10213649.html
Copyright © 2011-2022 走看看