目录:
一、前言
无论那种编程语言,特别是面向对象OOP(Object-Oriented Programming,简称 OOP)这种,在编写特定场景下,有对应编码方式有会对应的优势,这时候就需要用到设计模式。
"GoF"是软件设计里一个非常经典的缩写,指的是《Design Patterns: Elements of Reusable Object-Oriented Software》这本书的四位作者:
- Erich Gamma
- Richard Helm
- Ralph Johnson
- John Vlissides
他们被称为"Gang of Four(四人帮)",简称 GoF。这本书系统总结了 23 种经典设计模式,是面向对象设计的基石。
下面以C# 编程语言进行常见的GoF设计模式的编码样例、特点及应用场景!
二、常见的设计模式及应用
下面按工业或者实际开发用到较多进行排序并逐一介绍!
2.1单例模式(创建型)
定义:一个类在整个应用程序生命周期中只有一个实例,并且只有一个全局访问点(全局访问点:只能通过一个固定的访问入口来获取对象,这个入口由单例类自己提供)。
特点:
- 构造方法私有(private);
- 类内部(private)维护一个静态实例引用字段;
- 通过一个静态方法或属性来获取对应实例(对应私有字段),对应全局访问点;
- 确保线程安全(多线程环境下只能产生一个实例);
应用场景:
- 配置中心;
- 日志类;
- 全局缓存;
- 数据库连接/HttpClient;
2.1.1静态构造函数
代码样例:
csharp
/// <summary>
/// 简单的单例模式类,天然线程安全
/// </summary>
public class Singleton
{
/// <summary>
/// 私有的自身对象的字段
/// </summary>
private static readonly Singleton singleton=new Singleton();
/// <summary>
/// 公开的自身类属性,全局访问点
/// </summary>
public static Singleton GetSingleton => singleton;
/// <summary>
/// 私有的实例方法
/// </summary>
private Singleton() { }
}
2.1.2简单版本
csharp
public class Singleton
{
private static Singleton _instance;
private Singleton() { }
public static Singleton Instance
{
get
{
if (_instance == null)
_instance = new Singleton();
return _instance;
}
}
}
分析:基本使用,但是不加锁,线程不安全!
变样:可以增加lock锁,但是会获取对象时,有性能损耗!
2.1.3Lazy<T>版本
csharp
public class Singleton
{
private static readonly Lazy<Singleton> _instance =
new Lazy<Singleton>(() => new Singleton());
private Singleton() { }
public static Singleton Instance => _instance.Value;
}
分析:延迟加载 + 线程安全 + 最简洁!
Lazy<T> 表示某个对象 直到第一次使用时才会真正创建。
Lazy:懒加载(Lazy Initialization), .NET 提供的一个泛型类,用来实现"按需创建对象"。
2.2简单工厂(创建型)
定义:通过一个工厂类来统一管理对象的创建(把创建对象的逻辑从使用者那里抽离出来,让工厂来决定创建哪一个具体产品)。
特点:
- 抽象产品(接口/抽象类);
- 具体产品(实现类,有抽象产品的规范和约定的行为方法);
- 工厂类(负责创建对象);
应用场景:
- 需要经常切换不同模式;
- 客户端不想理解创建细节;
2.2.1基本样例
csharp
/// <summary>
/// 抽象产品
/// </summary>
public abstract class Product {
public abstract void Use();
public void Do() {
Console.WriteLine("Do something!");
}
}
/// <summary>
/// 实际产品A
/// </summary>
public class ProductA :Product
{
public void UseA() { }
public override void Use() { }
}
/// <summary>
/// 实际产品B
/// </summary>
public class ProductB : Product
{
public override void Use() { }
}
public class ProductC : Product
{
public override void Use() { }
}
/// <summary>
/// 工厂类
/// </summary>
public class FactoryMethod
{
public static Product Create(string type_) {
Product dstProduct_ = null;
switch (type_) {
case "A":
dstProduct_ = new ProductA();
break;
case "B":
dstProduct_ = new ProductB();
break;
case "C":
dstProduct_ = new ProductC();
break;
default:
throw new Exception();
}
return dstProduct_;
}
}
2.3抽象工厂(创建型)
定义:用于在不指定具体类的前提下,创建一族(Family)相关或互相依赖的对象(产品)。
特点:
- 定义不同的产品接口,然后在不同产品上各自实现接口 ;
- 定义抽象工厂接口,包含不同的产品接口 ;
- 不同工厂生产不同产品族;
应用场景:
- 操作系统相关 API 封装;
- UI 库(Windows/Mac/Linux);
2.3.1基本样例
设计代码:
csharp
#region 抽象产品
/// <summary>
/// 抽象产品A
/// </summary>
public interface IButton
{
void Click();
}
/// <summary>
/// 抽象产品B
/// </summary>
public interface ITextBox
{
void Display();
}
#endregion
#region 具体实现的产品分类
/// <summary>
/// 第1类的A
/// </summary>
public class WindowsButton : IButton
{
public void Click() => Console.WriteLine("Windows Button clicked");
}
/// <summary>
/// 第1类的B
/// </summary>
public class WindowsTextBox : ITextBox
{
public void Display() => Console.WriteLine("Windows TextBox displayed");
}
/// <summary>
/// 第2类的A
/// </summary>
public class MacButton : IButton
{
public void Click() => Console.WriteLine("Mac Button clicked");
}
/// <summary>
/// 第2类的B
/// </summary>
public class MacTextBox : ITextBox
{
public void Display() => Console.WriteLine("Mac TextBox displayed");
}
#endregion
#region 抽象工厂实现
/// <summary>
/// 抽象工厂
/// </summary>
public interface IUIFactory
{
IButton CreateButton();
ITextBox CreateTextBox();
}
/// <summary>
/// 第一类的工厂
/// </summary>
public class WindowsUIFactory : IUIFactory
{
public IButton CreateButton() => new WindowsButton();
public ITextBox CreateTextBox() => new WindowsTextBox();
}
/// <summary>
/// 第二类的工厂
/// </summary>
public class MacUIFactory : IUIFactory
{
public IButton CreateButton() => new MacButton();
public ITextBox CreateTextBox() => new MacTextBox();
}
#endregion
调用代码:
csharp
IUIFactory factory = new WindowsUIFactory(); // 或 MacUIFactory
IButton button = factory.CreateButton();
ITextBox textBox = factory.CreateTextBox();
button.Click();
textBox.Display();
分析:客户端完全不依赖具体产品类。
2.4代理模式(结构型)
定义:让一个对象(代理对象)控制对另一个对象(真实对象)的访问。给真实对象"加一层壳",增强功能但不改变其核心逻辑。
特点:
- 定义抽象接口;
- 真实对象和代理对象实现对应接口;
- 代理对象增加真实对象功能;
应用场景:
- 权限校验;
- 缓存结果,提高性能;
- 延迟初始化(懒加载);
- 远程访问(RMI、WebService 等);
- 监控访问次数、日志记录;
- 为对象创建前后添加 AOP 行为;
2.4.1基本样例
设计代码:
csharp
// <summary>
/// 抽象接口
/// </summary>
public interface ISubject
{
void DoWork();
}
/// <summary>
/// 真实对象
/// </summary>
public class RealSubject : ISubject
{
public void DoWork()
{
Console.WriteLine("RealSubject: 正在执行核心业务逻辑...");
}
}
/// <summary>
/// 代理对象
/// </summary>
public class Proxy : ISubject
{
private RealSubject _realSubject;
public Proxy()
{
_realSubject = new RealSubject();
}
public void DoWork()
{
Console.WriteLine("Proxy: 开始前置处理(例如日志记录)...");
_realSubject.DoWork();
Console.WriteLine("Proxy: 后置处理(例如监控、统计)...");
}
}
调用代码:
csharp
ISubject subject = new Proxy();
subject.DoWork();
四、参考资料
- 设计模式简介
- 快速记忆23种设计模式
- C# 单例模式讲解和代码示例
- C#设计模式(1)------单例模式
- <>
- <>
- <>
- <>
- <>
- <>
- <>
- <>
- <>
- <>
- <>
- <>
以上文章仅做参考学习,如有不足,敬请批评指正!