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***********"); }
}
}
DesignPatternPrinciple-设计模式原则的更多相关文章
- C#软件设计——小话设计模式原则之:依赖倒置原则DIP
前言:很久之前就想动笔总结下关于软件设计的一些原则,或者说是设计模式的一些原则,奈何被各种bootstrap组件所吸引,一直抽不开身.群里面有朋友问博主是否改行做前端了,呵呵,其实博主是想做“全战”, ...
- C#软件设计——小话设计模式原则之:单一职责原则SRP
前言:上篇C#软件设计——小话设计模式原则之:依赖倒置原则DIP简单介绍了下依赖倒置的由来以及使用,中间插了两篇WebApi的文章,这篇还是回归正题,继续来写写设计模式另一个重要的原则:单一职责原则. ...
- C#软件设计——小话设计模式原则之:接口隔离原则ISP
前言:有朋友问我,设计模式原则这些东西在园子里都讨论烂了,一搜一大把的资料,还花这么大力气去整这个干嘛.博主不得不承认,园子里确实很多这方面的文章,并且不乏出色的博文.博主的想法是,既然要完善知识体系 ...
- C#软件设计——小话设计模式原则之:开闭原则OCP
前言:这篇继续来看看开闭原则.废话少说,直接入正题. 软件设计原则系列文章索引 C#软件设计——小话设计模式原则之:依赖倒置原则DIP C#软件设计——小话设计模式原则之:单一职责原则SRP C#软件 ...
- 设计模式原则——依赖倒转&里氏代换原则
设计模式一共有六大原则: 单一原则.开放封闭原则.接口分离原则.里氏替换原则.最少知识原则.依赖倒置原则. 这篇博客是自己对依赖倒转&里氏代换原则的一些拙见,有何不对欢迎大家指出. 依赖倒转原 ...
- Java设计模式(二)设计模式原则
学习Java设计模式之前,有必要先了解设计模式原则. 开闭原则 定义 一个软件实体如类.模块和函数应该对扩展开放,对修改关闭 用抽象构建框架,用实现扩展细节 优点:提高软件系统的可复用性及可维护性 C ...
- DesignPatternPrinciple(设计模式原则)一
设计模式六大原则(1):单一职责原则 定义:不要存在多于一个导致类变更的原因.通俗的说,即一个类只负责一项职责. 问题由来:类T负责两个不同的职责:职责P1,职责P2.当由于职责P1需求发生改变而需 ...
- DesignPatternPrinciple(设计模式原则)二
设计模式六大原则(5):迪米特法则 定义:一个对象应该对其他对象保持最少的了解. 问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大. 解决方案:尽量降低类与类之 ...
- C++技术问题总结-第12篇 设计模式原则
设计模式六大原则,參见http://www.uml.org.cn/sjms/201211023.asp. 1. 单一职责原则 定义:不要存在多于一个导致类变更的原因.通俗的说,即一个类仅仅负责一项职责 ...
- 设计模式原则(6)--Open-Closed Principle(OCP)--开闭原则
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.定义: 一个软件实体应当对扩展开放,对修改关闭.即软件实体应尽量在不修改原有代码的情况下进行扩展. 2.使用场 ...
随机推荐
- RequestMappingHandlerMapping请求地址映射流程!
上篇文章里,我们讲解了RequestMappingHandlerMapping请求地址映射的初始化流程,理解了@Controller和@RequestMapping是如何被加载到缓存中的. 今天我们来 ...
- IDEA中给源码添加自己注释——private-notes插件安装使用
一.前言 我们在空闲之余喜欢研究一些经典框架的源码,发现没办法把自己的注释添加上. 会给出提示:File is read-only 很烦,但是为了安全考虑也是没有办法的! 这是一个大佬就写了一个IDE ...
- [常用工具] shell脚本快速入门笔记
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 脚本(shell script),是一种为 shell 编写的脚本程序.业界所说的 shell 通常都是指 sh ...
- Asp-Net-Core-搭建ELK日志平台-Docker-Compose版本
title: Asp.Net Core 搭建ELK日志平台(Docker-Compose版本) date: 2022-09-27 15:16:59 tags: - .NET 由于暂时用不上Logsta ...
- 克拉玛依初赛-wp
MISC 签到 16进制转字符串 base64 再来一次base64 flag 论禅论道 7z解压得到jar 使用decom打开 解密 得到flag WEB pingme 抓包,修改POST提交的参数 ...
- mysql常用命令,检查数据库连接情况以及修改时区
常用操作 注:也可以运行 mysql -u 用户名(root) -p 密码(root) 数据库名(bank) ,然后回车 导入文件:source e:bank.sql (你的sql文件) 回车 PS ...
- 2023牛客寒假算法基础集训营4 A-H+JLM
比赛链接 A 题解 知识点:数学. 算一下发现 \(3\) 最好,\(2,4\) 并列, \(4\) 以后递减.于是,特判 \(3\) ,其他取最小值. (众所周知, \(e\) 进制最好qwq. 时 ...
- Django3.X使用富文本编辑器kindereditor上传图片时一直转圈圈,如何解决
问题描述: 在写bbs项目的时候,老师用的是Django1.X结合富文本编辑器kindeditor,实现了图片上传,但是我在用Django3.X的时候,代码和老师一模一样,上传图片的时候一直转圈圈?? ...
- 9月22日内容总结——计算机五大组成部分详解、编程语言及发展史、python解释器安装与环境变量设置
内容总结 目录 内容总结 一.计算机五大组成部分详细介绍 1.控制器 2.运算器 3.存储设备 4.输入设备 5.输出设备 二.计算机三大核心硬件 1. cpu 2.内存 举例:写文档时,突然关机了. ...
- java通过idea启动查看类加载来源信息
本文为博主原创,转载请注明出处: jdk 8 环境时,可以在启动的环境中配置 :-XX:+TraceClassLoading 进行启动时查看 jdk 11 环境时,可以在启动的JVM 环境中配置 ...