原型模式
1、定义与核心思想
(1)定义
- 原型模式(Prototype Pattern)属于创建型设计模式,通过复制现有对象(原型)创建新对象,无需显式调用构造函数。
- 其核心是通过克隆(Clone)操作实现对象的高效创建,适用于初始化成本高的场景。
(2)核心思想
- 基于现有对象创建新对象,避免重复初始化。
- 隔离对象创建细节,提升性能与灵活性。
(3)结构及角色
- 抽象原型(IPrototype):声明克隆接口(如
ICloneable)。 - 具体原型(ConcretePrototype):实现克隆方法,支持浅拷贝或深拷贝。
- 客户端:通过原型实例调用克隆方法生成新对象。
2、C#代码实现
(1)浅拷贝实现
public interface IPrototype
{IPrototype Clone();
}
public class ConcretePrototype : IPrototype
{public int Id { get; set; }public string Name { get; set; }public List<string> Tags { get; set; } public IPrototype Clone(){return (IPrototype)this.MemberwiseClone();}
}
var original = new ConcretePrototype { Id = 1, Name = "原型", Tags = new List<string> { "Tag1" } };
var cloned = original.Clone() as ConcretePrototype;Console.WriteLine(cloned.Name);
original.Tags.Add("Tag2");
Console.WriteLine(cloned.Tags.Count);
(2)深拷贝实现
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;public static T DeepClone<T>(T obj)
{using (var ms = new MemoryStream()){var formatter = new BinaryFormatter();formatter.Serialize(ms, obj);ms.Position = 0;return (T)formatter.Deserialize(ms);}
}
public IPrototype Clone()
{return DeepClone(this);
}
original.Tags.Add("Tag2");
Console.WriteLine(cloned.Tags.Count);
(3)实战案例
- 游戏角色生成系统:快速生成预配置角色,支持动态修改属性。
public abstract class CharacterPrototype : ICloneable
{public string Name { get; set; }public int Health { get; set; }public List<Skill> Skills { get; set; }public object Clone(){var clone = (CharacterPrototype)this.MemberwiseClone();clone.Skills = new List<Skill>(this.Skills); return clone;}
}
public class Warrior : CharacterPrototype
{public Warrior() {Name = "默认战士";Health = 100;Skills = new List<Skill> { new Skill("斩击") };}
}
var originalWarrior = new Warrior();
var clonedWarrior = originalWarrior.Clone() as Warrior;
clonedWarrior.Name = "克隆战士";
clonedWarrior.Skills.Add(new Skill("格挡"));Console.WriteLine(originalWarrior.Skills.Count);
(4)最佳实践
- 优先实现
ICloneable接口:规范克隆行为。 - 深拷贝安全性:使用序列化或手动复制引用对象。
- 结合工厂模式:通过原型注册表管理多种原型。
3、优缺点对比
(1)优点
- 性能优化:跳过构造函数执行,直接复制内存数据。
- 简化对象创建:隐藏复杂对象的构建细节。
- 动态扩展:通过修改原型状态批量生成衍生对象。
(2)缺点
- 深拷贝实现复杂:需处理循环引用、序列化限制等问题。
- 破坏封装性:直接访问私有成员可能导致意外修改。
(3)对比其他模式
| 模式 | 区别点 | 适用场景 |
|---|
| 工厂模式 | 通过子类创建新对象 | 需要明确类层次结构的场景 |
| 单例模式 | 确保全局唯一实例 | 资源共享场景(如日志管理器) |
| 原型模式 | 通过克隆现有对象创建新实例 | 高效复制复杂对象 |
单例模式👍
1、定义与核心思想
(1)定义
- 单例模式(Singleton Pattern)是一种创建型设计模式,确保一个类仅有一个实例,并提供全局访问点。
- 其核心思想是控制实例化次数,减少资源消耗并保证数据一致性,单例模式能有效避免重复创建对象带来的性能问题。
- 例如,日志管理器、配置管理、数据库连接池等场景中。
(2)关键特性
- 唯一实例:通过私有构造函数防止外部实例化。
- 全局访问点:通过静态属性或方法提供实例访问。
- 线程安全:多线程环境下需确保实例唯一性。
(3)应用场景
- 配置管理:全局共享配置信息,避免重复加载文件。
- 日志系统:统一日志写入,防止多线程写入冲突。
- 数据库连接池:管理有限的数据库连接资源。
- 缓存管理器:全局缓存实例提高数据访问效率。
2、C#代码实现
(1)饿汉式
- 在类加载时立即初始化实例,线程安全但可能造成资源浪费。
- 优点:实现简单,线程安全(通过静态初始化保证)。
- 缺点:类加载时实例化,若实例未使用则浪费内存。
public sealed class SingletonEager {private static readonly SingletonEager _instance = new SingletonEager();private SingletonEager() { } public static SingletonEager Instance => _instance;
}
(2)懒汉式
- 延迟实例化,首次调用时创建对象,需解决线程安全问题。
- 基础版(非线程安全)
- 优点:实现延迟加载。
- 缺点:多线程环境下可能创建多个实例。
public sealed class SingletonLazy {private static SingletonLazy _instance;private SingletonLazy() { }public static SingletonLazy Instance {get {if (_instance == null) {_instance = new SingletonLazy();}return _instance;}}
}
- 线程安全版(使用锁)
- 实现:通过
lock 关键字保证线程安全。 - 缺点:每次访问实例时加锁,性能较低。
public sealed class SingletonSafe {private static SingletonSafe _instance;private static readonly object _lock = new object();private SingletonSafe() { }public static SingletonSafe Instance {get {lock (_lock) {if (_instance == null) {_instance = new SingletonSafe();}return _instance;}}}
}
(3)双重检查锁
- 优化锁机制,减少性能开销
- 优点:仅在首次实例化时加锁,提升性能.
public sealed class SingletonDoubleCheck {private static SingletonDoubleCheck _instance;private static readonly object _lock = new object();private SingletonDoubleCheck() { }public static SingletonDoubleCheck Instance {get {if (_instance == null) {lock (_lock) {if (_instance == null) {_instance = new SingletonDoubleCheck();}}}return _instance;}}
}
(4)静态内部类
- 利用CLR的静态初始化机制保证线程安全
- 优点:延迟加载且无需显式锁,由CLR自动处理
public sealed class SingletonNested {private SingletonNested() { }private static class Nested {internal static readonly SingletonNested Instance = new SingletonNested();}public static SingletonNested Instance => Nested.Instance;
}
(5)使用 Lazy(推荐)
- C# 4.0后提供
Lazy<T>类型,简化线程安全实现 - 优点:简洁且线程安全,默认使用
LazyThreadSafetyMode.ExecutionAndPublication模式
public sealed class SingletonLazyT {private static readonly Lazy<SingletonLazyT> _lazy = new Lazy<SingletonLazyT>(() => new SingletonLazyT());private SingletonLazyT() { }public static SingletonLazyT Instance => _lazy.Value;
}
3、进阶技巧
(1)防止反射破坏单例
通过标记构造函数为私有并添加实例存在性检查:
private Singleton() {if (_instance != null) {throw new Exception("实例已存在!");}
}
(2)序列化与反序列化
- 实现
ISerializable接口或使用[Serializable]特性时,需重写反序列化逻辑以防止生成新实例。
4、优缺点分析
(1)优点
- 资源节约:避免重复实例化。
- 数据一致性:全局唯一实例保证状态统一。
- 访问便捷:通过静态属性快速获取实例。
(2)缺点
- 违反单一职责原则:可能承担过多职责。
- 单元测试困难:全局状态难以模拟。
简单工厂模式👍
1、定义与核心思想
(1)定义
- 简单工厂模式(Simple Factory Pattern)属于创建型设计模式,通过一个工厂类封装对象的创建过程,客户端无需直接实例化具体类,而是通过传递参数到工厂方法中动态决定创建哪种对象。
- 核心目标是解耦对象的创建和使用,提升代码的可维护性和扩展性。
(2)核心角色
- 工厂类(Factory):负责根据输入参数创建具体产品对象,通常包含一个静态方法。
- 抽象产品(Product):定义所有具体产品的公共接口或基类。
- 具体产品(ConcreteProduct):实现抽象产品的子类,每个类对应一种产品类型。
(3)应用场景
- 对象创建逻辑简单:例如配置读取工具类(XML/JSON)、数据库连接池。
- 统一管理创建过程:如日志记录器(文件日志、数据库日志)。
- 快速原型开发:在需求未完全明确时,通过工厂隔离变化。
2、C#代码实现
(1)C#代码实现
- 以下模拟一个图形绘制系统,支持创建圆形(Circle)和矩形(Rectangle)对象
public interface IShape
{void Draw();
}
public class Circle : IShape
{public void Draw() => Console.WriteLine("绘制圆形");
}
public class Rectangle : IShape
{public void Draw() => Console.WriteLine("绘制矩形");
}
public class ShapeFactory
{public static IShape CreateShape(string shapeType){switch (shapeType.ToLower()){case "circle":return new Circle();case "rectangle":return new Rectangle();default:throw new ArgumentException("无效的图形类型");}}
}
class Program
{static void Main(string[] args){IShape circle = ShapeFactory.CreateShape("circle");circle.Draw(); IShape rectangle = ShapeFactory.CreateShape("rectangle");rectangle.Draw(); }
}
(2)代码解析
- 抽象产品接口(IShape):统一所有图形对象的绘制行为。
- 具体产品类(Circle/Rectangle):实现具体功能。
- 工厂类(ShapeFactory):通过静态方法
CreateShape根据参数动态创建对象。 - 客户端调用:无需关注具体类的构造细节,只需传递类型名称。
(3)实战案例
- 以下是一个基于简单工厂模式的计算器实现,支持加、减、乘、除运算
public abstract class Operation
{public double NumberA { get; set; }public double NumberB { get; set; }public abstract double Calculate();
}
public class AddOperation : Operation
{public override double Calculate() => NumberA + NumberB;
}public class SubtractOperation : Operation
{public override double Calculate() => NumberA - NumberB;
}
public class OperationFactory
{public static Operation CreateOperation(string operator){switch (operator){case "+": return new AddOperation();case "-": return new SubtractOperation();default: throw new ArgumentException("无效运算符");}}
}
var operation = OperationFactory.CreateOperation("+");
operation.NumberA = 10;
operation.NumberB = 5;
Console.WriteLine(operation.Calculate());
(4)最佳实践
- 优先使用简单工厂的场景:产品类型固定且逻辑简单时,快速实现解耦。
- 避免滥用的情况:产品类型频繁变化或需要高扩展性时,应升级为工厂方法模式。
- 结合其他模式优化:如通过依赖注入(DI)容器管理工厂生命周期。
3、进阶技巧
(1)通过反射优化
- 使用反射技术动态创建对象,避免硬编码类型判断
- 优势:新增产品时无需修改工厂类
public class ReflectionShapeFactory
{public static IShape CreateShape(string className){Type type = Type.GetType($"Namespace.{className}"); return (IShape)Activator.CreateInstance(type);}
}
(2)结合配置文件
- 通过配置文件(如JSON/XML)定义产品类型,实现完全解耦
- 适用场景:需要动态切换产品类型的系统
{"ShapeType": "Circle"
}
string shapeType = LoadConfigFromFile("config.json");
IShape shape = ShapeFactory.CreateShape(shapeType);
4、优缺点分析
(1)优点
- 解耦客户端与具体类:客户端仅依赖抽象接口,避免直接耦合具体实现。
- 集中管理对象创建:将创建逻辑集中在工厂类中,便于统一维护和扩展。
- 简化客户端代码:客户端仅需传递参数,无需处理复杂构造逻辑。
(2)缺点
- 违反开闭原则:新增产品类型需修改工厂类代码,可能引入风险。
- 工厂类职责过重:当产品类型过多时,工厂类会变得臃肿。
- 扩展性受限:适用于产品类型较少的场景,复杂场景需升级为工厂方法模式。
(3)对比其他模式
| 模式类型 | 核心区别 | 适用场景 |
|---|
| 简单工厂模式 | 单一工厂类,通过参数创建所有对象 | 产品类型少且不频繁变化 |
| 工厂方法模式 | 每个产品对应一个工厂类,客户端决定使用哪个 | 产品类型多且需灵活扩展 |
| 抽象工厂模式 | 创建产品家族,确保产品兼容性 | 需要一组相关或依赖对象的复杂系统 |