# design-patterns-for-csharp **Repository Path**: chenyanbo1024/design-patterns-for-csharp ## Basic Information - **Project Name**: design-patterns-for-csharp - **Description**: C# 设计模式 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-10-11 - **Last Updated**: 2021-10-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # C# 设计模式 ## A . 创建型模式 > 创建型模式关注点是如何创建对象,其核心思想是要把对象的创建和使用相分离,这样使得两者能相对独立地变换。 > > 创建型模式包括: > > - 工厂方法:Factory Method > - 抽象工厂:Abstract Factory > - 建造者:Builder > - 原型:Prototype > - 单例:Singleton ### 01 | 单例模式 > 单例设计模式(Singleton Design Pattern):一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。 #### 应用场景 1. 一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。 2. 计数器 3. 连接对象,比如 Redis 、I/O 等连接。 #### 实现单例的几种方式 1. 饿汉式(非延迟加载) 2. 懒汉式(延迟加载) 3. 双重检测 #### 性能对比 延迟加载的作用:理论上可以有效提高系统资源的利用效率。 饿汉式与懒汉式的区别就是支不支持 "延迟加载" ,延迟加载就是等到真正需要用到的时候才去创建实例,减少了内存开销等。但是如果初始化耗时会很长,那在等到需要时才去初始化显然不是一个正确的选择,因为这样可能会导致一个接口的响应时长变长,甚至超时。 ### 02 | 工厂模式 > 定义一个用于创建对象的接口,让子类决定实例化哪一个类。*Factory Method* 使一个类的实例化延迟到其子类。 #### 工厂模式 的细分类型 > *GoF* 的《设计模式》一书中,它将简单工厂模式看作是工厂方法模式的一种特例,所以工厂模式被分成了 工厂方法 和 抽象工厂 两类。 更为普遍的区分方式: 1. 简单工厂(*Simple Factory*) 2. 工厂方法(*Factory Method*) 3. 抽象工厂(*Abstract Factory*) #### 几种类型的常用程度 简单工厂和工厂方法比较常用,抽象工厂的应用场景比较特殊,所以很少用到。 #### 应用场景 1. 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2. 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3. 设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。 #### 是否需要 工厂模式 的 4 个标准 1. 封装变化:创建逻辑有可能变化,封装成工厂类之后,创建逻辑的变更对调用者透明。 2. 代码复用:创建代码抽离到独立的工厂类之后可以复用。 3. 隔离复杂性:封装复杂的创建逻辑,调用者无需了解如何创建对象。 4. 控制复杂度:将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。 ### 03 | 建造者模式 > 建造者(*Builder*)模式,是一种创建型设计模式,中文翻译为 **建造者模式** 或者 **构建者模式** ,也有人叫它 **生成器模式**。 > > 建造者模式可以将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 #### 为什么需要建造者模式 一般情况下,创建对象我们都是通过 **构造函数** 或者 **Set方法** 来创建的,当面对一个比较简单的对象的时候,这两种方式都能很好的实现我们需要的功能。 但是当一个对象创建所需参数很长,其中还有必填选填参数,然后可能各个参数之间还会相互依赖,比如当 参数A 为 true 时,参数B 为必填,否则为选填。这种复杂情况下,我们就需要建造者模式来帮助我们更好的创建对象,实现代码的易读性、可扩展性了。 #### 应用场景 1. 需要生成的对象具有复杂的内部结构。 2. 需要生成的对象内部属性本身相互依赖。 3. 肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的 "套餐" 。 4. *C#* 中的 *StringBuilder* #### 建造者模式 与 工厂模式 的区别 - 工厂模式是用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子 类),由给定的参数来决定创建哪种类型的对象。 - 建造者模式是用来创建一种类型的复杂对 象,通过设置不同的可选参数,“定制化”地创建不同的对象。 ### 04 | 原型模式 > 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 #### 原型模式的原理 在 *Javascript* 中,原型模式一种常用的设计模式。因为 *Javascript* 本身就是一种基于原型开发的语言。对于常用 *C#* 这种编程语言的我们来说,实际开发就很少用到原型模式了。 原型模式的原理:当对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同), 在这种情况下,可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型设计模式 (Prototype Design Pattern),简称原型模式。 #### 原型模式的实现方式:深拷贝与浅拷贝 > 在 *C#* 中,值类型默认是深拷贝,引用类型默认是浅拷贝。 > > *C#* 深拷贝实现方式:反射 和 序列化 - 深拷贝:复制对象的引用,同时拷贝对象的值。拷贝对象与源对象相互独立,任何一个对象的值变动不会影响另一个对象。 - 浅拷贝:仅复制对象的引用,不会拷贝对象的值。拷贝对象与源对象实际是指向同一块内存空间,对象值变动会相互影响。 ## B. 结构性模式 > 结构型模式主要涉及如何组合各种对象以便获得更好、更灵活的结构。虽然面向对象的继承机制提供了最基本的子类扩展父类的功能,但结构型模式不仅仅简单地使用继承,而更多地通过组合与运行期的动态组合来实现更灵活的功能。 > > 结构型模式有: > > - 代理模式:Proxy Design Pattern > - 桥接模式 > - 装饰器模式 > - 适配器模式 > - 门面模式 > - 组合模式 > - 享元模式 ### 05 | 代理模式 > 代理模式(Proxy Design Pattern):在不改变原始类 (或叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能。