DesignPatternPrinciple-设计模式原则

1. 单一职责原则(Single Responsibility Principle)类T负责两个不同的职责:职责P1,职责P2。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternPrinciple.SRP
{
    /// <summary>
    /// 单一职责原则:类T负责两个不同的职责:职责P1,职责P2。当由于职责P1需求发生改变而需要修改类T时,
    /// 有可能会导致原本运行正常的职责P2功能发生故障。
    /// 
    /// 一个类只负责一件事儿
    /// 面向对象语言开发,类是一个基本单位,单一职责原则就是封装的粒度
    /// 
    /// 写分支判断,然后执行不同的逻辑,其实这就违背了单一职责原则,但是功能是可以实现的
    /// 
    /// 拆分父类+子类,
    /// 每个类很简单,简单意味着稳定 意味着强大
    /// (现在的东西没有以前经用,因为功能多了,这不坏那坏了)
    /// 
    /// 拆分后,也会造成代码量的增加,
    /// 类多了,使用成本也高(理解成本)
    /// 
    /// 究竟该什么时候使用单一职责原则呢?
    /// 如果类型足够简单,方法够少,是可以在类级别去违背单一职责
    /// 如果类型复杂了,方法多了,建议遵循单一职责原则
    /// 
    /// 方法级别的单一职责原则:一个方法只负责一件事儿(职责分拆小方法,分支逻辑分拆)
    ///   类级别的单一职责原则:一个类只负责一件事儿
    /// 类库级别的单一职责原则:一个类库应该职责清晰
    /// 项目级别的单一职责原则:一个项目应该职责清晰(客户端/管理后台/后台服务/定时任务/分布式引擎)
    /// 系统级别的单一职责原则:为通用功能拆分系统(IP定位/日志/在线统计)
    /// 
    /// </summary>
    public class SRPShow
    {
        public static void Show()
        {
            {
                Animal animal = new Animal("");//呼吸空气
                animal.Breath();
                //animal.Action();
            }
            {
                Animal animal = new Animal("");//呼吸空气
                animal.Breath();
                //animal.Action();
            }
            {
                Animal animal = new Animal("");//呼吸水
                animal.Breath();
                animal.Action();
            }
            {
                AbstractAnimal animal = new Chicken();
                animal.Breath();
                animal.Action();
            }
            {
                AbstractAnimal animal = new Fish();
                animal.Breath();
                animal.Action();
            }
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternPrinciple.SRP
{
    /// <summary>
    /// 封装
    /// 动物类
    /// 简单意味着稳定
    /// </summary>
    public class Animal
    {
        private string _Name = null;
        public Animal(string name)
        {
            this._Name = name;
        }
        /// <summary>
        /// 这个方法就挺不稳定,经常各种分支变化经常修改
        /// </summary>
        public void Breath()
        {
            if (this._Name.Equals(""))
                Console.WriteLine($"{this._Name} 呼吸空气");
            else if (this._Name.Equals(""))
                Console.WriteLine($"{this._Name} 呼吸空气");
            else if (this._Name.Equals(""))
                Console.WriteLine($"{this._Name} 呼吸水");
            else if (this._Name.Equals("蚯蚓"))
                Console.WriteLine($"{this._Name} 呼吸泥土");
        }
        //BreathChicken  BreathFish

        //应该拆分了
        public void Action()
        {
            if (this._Name.Equals(""))
                Console.WriteLine($"{this._Name} flying");
            else if (this._Name.Equals(""))
                Console.WriteLine($"{this._Name} walking");
            else if (this._Name.Equals(""))
                Console.WriteLine($"{this._Name} Swimming");
            else if (this._Name.Equals("蚯蚓"))
                Console.WriteLine($"{this._Name} Crawling");
        }
    }
}

 

2. 里氏替换原则(Liskov Substitution Principle):任何使用基类的地方,都可以透明的使用其子类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternPrinciple.LSP
{
    /// <summary>
    /// 里氏替换原则:任何使用基类的地方,都可以透明的使用其子类
    /// 继承、多态
    /// 继承:子类拥有父类的一切属性和行为,任何父类出现的地方,都可以用子类来代替
    /// 继承+透明(安全,不会出现行为不一致)
    /// 
    /// 1 父类有的,子类是必须有的;
    ///   如果出现了子类没有的东西,那么就应该断掉继承;
    ///   (再来一个父类,只包含都有的东西)
    /// 2 子类可以有自己的属性和行为
    ///   子类出现的地方,父类不一定能代替
    ///   白马非马
    /// 3 父类实现的东西,子类就不要再写了,(就是不要new隐藏)
    ///   有时候会出现意想不到的情况,把父类换成子类后,行为不一致
    ///   如果想修改父类的行为,通过abstract/virtual
    ///   
    /// 声明属性、字段、变量,尽量声明为父类(父类就能满足)
    /// 
    /// </summary>
    public class LSPShow
    {
        public static void Show()
        {
            Console.WriteLine("***************************");
            Poly.Test();
            {
                //People people = new Chinese();
                Chinese people = new Chinese();
                people.Traditional();
                //DoChinese(people);
                people.SayHi();
            }
            {
                Chinese people = new Hubei();
                people.Traditional();
                //DoChinese(people);
                people.SayHi();

            }
            {
                var people = new Hubei();
                people.Traditional();
                //DoChinese(people);
                people.SayHi();
            }
            {
                People people = new Japanese();
                people.Traditional();
                //要么上端调用去判断  不能写  因为Japanese没有Traditional
                //要么就只能在子类抛异常
            }
            {
                Hubei people = new Hubei();
                people.Traditional();
                DoChinese(people);
                DoHubei(people);
            }

            {
                //People people = new People();
                //Do(people);
            }

        }

        private static void DoChinese(Chinese people)
        {
            Console.WriteLine($"{people.Id} {people.Name} {people.Kuaizi}");
            people.SayHi();
        }



        private static void DoHubei(Hubei people)
        {
            Console.WriteLine($"{people.Id} {people.Name} {people.Kuaizi}");
            people.SayHi();
        }

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternPrinciple.LSP
{
    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("早上好,过早了么?");
        }
    }

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

    public class Japanese : People
    {
        //public int Id { get; set; }
        //public string Name { get; set; }
        //public new void Traditional()
        //{
        //    Console.WriteLine("忍者精神 ");
        //throw new Exception();
        //}
        //Traditional也会继承 但是Japanese又没有Traditional
        public void Ninja()
        {
            Console.WriteLine("忍者精神 ");
        }

    }

}


3. 依赖倒置原则(Dependence Inversion Principle)依赖倒置原则:上层模块不应该依赖于低层模块,二者应该通过抽象依赖

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternPrinciple.DIP
{
    /// <summary>
    /// 依赖倒置原则:高层模块不应该依赖于低层模块,二者应该通过抽象依赖
    ///              依赖抽象,而不是依赖细节
    /// 抽象:接口/抽象类--可以包含没有实现的元素
    /// 细节:普通类--一切都是确定的
    /// 
    /// 面向抽象编程:尽量的使用抽象,80%的设计模式都是跟抽象有关
    /// 属性 字段  方法参数 返回值。。。尽量都是抽象
    /// 
    /// 
    /// </summary>
    public class DIPShow
    {
        public static void Show()
        {
            Console.WriteLine("**************DIPShow***************");
            Student student = new Student()
            {
                Id = 191,
                Name = "候鸟班长"
            };
            //Student-使用-手机
            //高层---------底层
            {
                iPhone phone = new iPhone();
                student.PlayiPhone(phone);
                student.PlayT(phone);
                student.Play(phone);
            }
            {
                Lumia phone = new Lumia();
                student.PlayLumia(phone);
                student.PlayT(phone);
                student.Play(phone);
            }
            {
                Honor phone = new Honor();
                student.PlayHonor(phone);
                student.PlayT(phone);
                student.Play(phone);
            }
            //依赖细节  高层就依赖了底层
            //手机扩展一下,学生就得改一下。。。手机多了怎么办
            {
                Mi phone = new Mi();
                student.PlayT(phone);
                student.Play(phone);
            }
            {
                Oppo phone = new Oppo();
                student.PlayT(phone);
                student.Play(phone);
            }
            //用泛型+父类约束其实就等同于用父类参数类型
            //面向抽象有啥好处? 
            //1 一个方法满足不同类型的参数,
            //2 还支持扩展,只要是实现了这个抽象,不用修改Student
            {
                //面向抽象后,不能使用子类的特别内容
                Mi phone = new Mi();
                student.Play(phone);
                //如果传递的是Mi,Bracelet是有的,但是方法确实不能用
                //编译器决定了是不能用Bracelet的(dynamic/反射是可以调用的)

                //不能常规调用,这个问题是解决不了的,
                //因为面向抽象不止一个类型,用的就是通用功能;非通用的,那就不应该面向抽象
            }
            //面向抽象,只要抽象不变,高层就不变
            //面向对象语言开发,就是类与类之间进行交互,如果高层直接依赖低层的细节,细节是多变的,那么低层的变化就导致上层的变化;如果层数多了,底层的修改会直接水波效应传递到最上层,一点细微的改动都会导致整个系统从下往上的修改(这就是大家经常加班的原因)
            //面向抽象,如果高层和低层没有直接依赖,而是依赖于抽象,抽象一般是稳定的,那低层细节的变化扩展就不会影响到高层,这样就能支持层内部的横向扩展,不会影响其他地方,这样的程序架构就是稳定的

            //依赖倒置原则(理论基础)---IOC控制反转(实践封装)---DI依赖注入(实现IOC的手段)
        }
    }
}

 

4. 接口隔离原则(Interface Segregation Principle):客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternPrinciple.ISP
{
    /// <summary>
    /// 接口隔离原则:客户端不应该依赖它不需要的接口;
    ///              一个类对另一个类的依赖应该建立在最小的接口上;
    /// </summary>
    public class ISPShow
    {
        public static void Show()
        {
            Console.WriteLine("***************ISPShow*************");
            Student student = new Student()
            {
                Id = 191,
                Name = "候鸟班长"
            };
            //AbstractPhone定义了id branch call text    is  a
            //现有智能手机map movie online game..
            //是否该把这几个上升到AbstractPhone? 
            //不应该的,上升后,oldman也是手机,但是没有这些功能!
            //AbstractPhone就只能放入任何手机都必须具备的功能
            {
                OldMan phone = new OldMan();
                phone.Call();
                phone.Text();
            }
            //不适合放在抽象类,但是面向抽象编程,接口!
            //接口interface定义 can do   不局限产品
            //Camera能拍照,能录像
            //既然面向抽象,那么有这些功能的对象都得能传递进来
            //那就让Camera也去实现IExtend
            {
                Honor honor = new Honor();
                student.Happy(honor);
                student.Video(honor);
            }
            {
                Camera camera = new Camera();
                student.Video(camera);
            }
            //实现IExtend接口,Camera出现很多自己没有的功能,
            //不应该用这种大而全的接口
            {
                IExtendVideo camera = new Camera();
                student.Video(camera);
            }

            {
                IExtendHappy extend = new TV();
                student.Happy(extend);
            }
            {
                IExtendGame extend = new PSP();
                student.Happy(extend);
            }
            //拆下去,都拆成一个方法一个接口,肯定也不好!
            {
                //List<>
                //Dictionary
                //IList<T>        索引相关
                //ICollection<T>  集合相关操作
                //IEnumerable<T>  迭代器foreach
            }
            //接口到底该如何定义?  
            //1 既不能是大而全,会强迫实现没有的东西,也会依赖自己不需要的东西
            //2 也不能一个方法一个接口,这样面向抽象也没有意义的
            //按照功能的密不可分来定义接口,
            //而且应该是动态的,随着业务发展会有变化的,但是在设计的时候,要留好提前量,避免抽象的变化
            //没有标准答案,随着业务和产品来调整的

            //3 接口合并 Map--定位/搜索/导航   这种属于固定步骤,业务细节,尽量的内聚,在接口也不要暴露太多业务细节
        }
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternPrinciple.ISP
{
    public class Honor : AbstractPhone, IExtend, IExtendVideo, IExtendHappy
    {
        public override void Call()
        {
            Console.WriteLine("User {0} Call", this.GetType().Name);
        }

        public override void Text()
        {
            Console.WriteLine("User {0} Call", this.GetType().Name);
        }

        public void Photo()
        {
            Console.WriteLine("User {0} Photo", this.GetType().Name);
        }

        public void Online()
        {
            Console.WriteLine("User {0} Online", this.GetType().Name);
        }

        public void Game()
        {
            Console.WriteLine("User {0} Game", this.GetType().Name);
        }

        public void Map()
        {
            Console.WriteLine("User {0} Map", this.GetType().Name);
        }

        public void Pay()
        {
            Console.WriteLine("User {0} Pay", this.GetType().Name);
        }

        public void Record()//录音
        {
            Console.WriteLine("User {0} Record", this.GetType().Name);
        }

        public void Movie()
        {
            Console.WriteLine("User {0} Movie", this.GetType().Name);
        }
    }
}

5. 迪米特法则 (Law Of Demeter):一个对象应该对其他对象保持最少的了解。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternPrinciple.LOD
{
    /// <summary>
    /// 迪米特法则(最少知道原则):一个对象应该对其他对象保持最少的了解。
    /// 只与直接的朋友通信。
    /// 面向对象语言---万物皆对象---类和类交互才能产生功能--这不就耦合了吗?
    /// 
    /// 类与类之间的关系:
    /// 纵向:继承≈实现(最密切)
    /// 横向:聚合> 组合> 关联> 依赖(出现在方法内部)
    /// 
    /// 高内聚低耦合
    /// 迪米特法则,降低类与类之间的耦合
    ///     只与直接的朋友通信,就是要尽量避免依赖更多类型
    /// 基类库(BCL--框架内置的)的类型除外     
    ///
    /// 迪米特,也会增加一些成本
    /// 
    /// 工作中有时候会去造一个中介/中间层
    /// 门面模式 中介者模式  分层封装
    /// 上层UI下订单---订单系统&支付系统&仓储&物流
    /// 门面模式--上层交互门面--门面依赖子系统
    /// 三层架构:UI---BLL---DAL
    /// 
    /// 去掉内部依赖
    /// 降低访问修饰符权限
    /// private
    /// protected
    /// internal
    /// protected internal 子类或者同类库
    /// public
    /// 
    /// 迪米特,依赖别人更少,让别人了解更少
    /// </summary>
    public class LODShow
    {
        public static void Show()
        {
            Console.WriteLine("************************");
            School school = new School()
            {
                SchoolName = "SchoolName",
                ClassList = new List<Class>()
                {
                    new Class()
                    {
                        ClassName="CN",
                        StudentList=new List<Student>()
                        {
                            new Student()
                            {
                                StudentName="Tony"
                            },
                            new Student()
                            {
                                StudentName="sada"
                            }
                        }
                    }
                }
            };

            school.Manage();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternPrinciple.LOD
{
    /// <summary>
    /// 学生
    /// </summary>
    public class Student
    {
        public int Id { get; set; }
        public string StudentName { get; set; }
        public int Height { private get; set; }

        public int Salay;

        public void ManageStudent()
        {
            Console.WriteLine(" {0}Manage {1} ", this.GetType().Name, this.StudentName);
        }
    }
}

6: 开闭原则 (Open Closed Principle):对扩展开发,对修改关闭

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternPrinciple.OCP
{
    /// <summary>
    /// 开闭原则:对扩展开发,对修改关闭
    ///    修改:修改现有代码(类)
    ///    扩展:增加代码(类)
    /// 面向对象语言是一种静态语言,最害怕变化,会波及很多东西 全面测试
    /// 最理想就是新增类,对原有代码没有改动,原有的代码才是可信的
    /// 
    /// 开闭原则只是一个目标,并没有任何的手段,也被称之为总则
    ///     其他5个原则的建议,就是为了更好的做到OCP
    ///     开闭原则也是面向对象语言开发一个终极目标
    ///     
    /// 如果有功能增加/修改的需求:
    /// 修改现有方法---增加方法---增加类---增加/替换类库
    /// </summary>
    public class OCPShow
    {
        public static void Show()
        {
            Console.WriteLine("*************OCPShow***********");
       
        }
    }
}

 

posted @ 2023-02-22 13:50  Tammytan  阅读(24)  评论(0编辑  收藏  举报