- 作者:老汪软件技巧
- 发表时间:2024-09-29 10:01
- 浏览量:
在本系列的第一部分中,我们探讨了两种基础的创建型设计模式:单例模式(Singleton) 和 工厂方法模式(Factory Method)。这些模式帮助管理 C# 中的对象创建,提供了将对象创建过程与业务逻辑解耦的方法。
现在,让我们深入探讨三种更高级的创建型设计模式:抽象工厂模式(Abstract Factory)、建造者模式(Builder) 和 原型模式(Prototype),这些模式解决了更复杂的对象创建场景。
抽象工厂模式(Abstract Factory)什么是抽象工厂?
抽象工厂模式为创建一组相关或依赖的对象提供了一个接口,而无需指定它们的具体类。它允许客户端使用工厂方法创建对象,但具体的实例化过程由子类决定。
现实生活类比
想象一个工厂生产不同风格的家具,比如现代风格或维多利亚风格。每种风格都有一系列相关的产品,例如椅子、沙发和桌子。抽象工厂将定义一个家具产品家族,而具体工厂(如 ModernFactory 和 VictorianFactory)则负责根据选择的风格创建正确的家具类型。
它解决了什么问题?
在系统需要创建一组相关且必须协同工作的对象时,抽象工厂模式非常有用。例如,UI 工具包通常需要创建特定平台的控件(如按钮和窗口),这些控件需要彼此兼容。
如何在 C# 中实现
以下是一个使用抽象工厂模式的 C# 示例,展示如何为不同平台创建按钮和窗口的产品家族:
// 抽象产品
public interface IButton
{
void Render();
}
public interface IWindow
{
void Render();
}
// Windows 的具体产品
public class WindowsButton : IButton
{
public void Render() => Console.WriteLine("渲染 Windows 按钮");
}
public class WindowsWindow : IWindow
{
public void Render() => Console.WriteLine("渲染 Windows 窗口");
}
// MacOS 的具体产品
public class MacButton : IButton
{
public void Render() => Console.WriteLine("渲染 Mac 按钮");
}
public class MacWindow : IWindow
{
public void Render() => Console.WriteLine("渲染 Mac 窗口");
}
// 抽象工厂
public interface IGUIFactory
{
IButton CreateButton();
IWindow CreateWindow();
}
// 具体工厂
public class WindowsFactory : IGUIFactory
{
public IButton CreateButton() => new WindowsButton();
public IWindow CreateWindow() => new WindowsWindow();
}
public class MacFactory : IGUIFactory
{
public IButton CreateButton() => new MacButton();
public IWindow CreateWindow() => new MacWindow();
}
// 客户端代码
public class Application
{
private IButton _button;
private IWindow _window;
public Application(IGUIFactory factory)
{
_button = factory.CreateButton();
_window = factory.CreateWindow();
}
public void Render()
{
_button.Render();
_window.Render();
}
}
// 使用示例
var windowsApp = new Application(new WindowsFactory());
windowsApp.Render();
var macApp = new Application(new MacFactory());
macApp.Render();
何时使用
抽象工厂模式非常适合需要创建一组相关对象的场景,比如 UI 组件,这些组件必须能够无缝协同工作。
常见陷阱现实案例
跨平台 UI 开发通常使用抽象工厂模式,以确保像按钮和窗口这样的组件与它们的环境(例如 Windows 或 macOS)兼容。
建造者模式(Builder)什么是建造者模式?
建造者模式用于一步步构建复杂对象。与其他创建型模式不同,建造者不要求产品具有通用接口,因此可以灵活地构建不同的对象表现形式。
现实生活类比
想象一下建造一座房子。房子由许多部分组成(例如,地基、墙壁、屋顶),不同类型的房子可能需要以不同方式组装这些部分。建造者模式允许逐步构建对象,提供了灵活性来控制对象的创建过程。
它解决了什么问题?
建造者模式简化了需要多个步骤才能构建的复杂对象。与其通过一个包含大量参数的构造函数来创建对象,建造者模式使构造过程更具可读性和可管理性。
如何在 C# 中实现
以下是一个使用建造者模式来构建房子的 C# 示例:
// 产品类
public class House
{
public string Walls { get; set; }
public string Roof { get; set; }
public string Foundation { get; set; }
public void ShowDetails()
{
Console.WriteLine($"这是一座有 {Walls}, {Roof}, 和 {Foundation} 的房子");
}
}
// 生成器接口
public interface IHouseBuilder
{
void BuildWalls();
void BuildRoof();
void BuildFoundation();
House GetHouse();
}
// 石头房子的具体生成器
public class StoneHouseBuilder : IHouseBuilder
{
private House _house = new House();
public void BuildWalls() => _house.Walls = "石墙";
public void BuildRoof() => _house.Roof = "石屋顶";
public void BuildFoundation() => _house.Foundation = "混凝土地基";
public House GetHouse() => _house;
}
// 导演类
public class HouseDirector
{
private IHouseBuilder _builder;
public HouseDirector(IHouseBuilder builder)
{
_builder = builder;
}
public House ConstructHouse()
{
_builder.BuildWalls();
_builder.BuildRoof();
_builder.BuildFoundation();
return _builder.GetHouse();
}
}
// 使用示例
var stoneBuilder = new StoneHouseBuilder();
var director = new HouseDirector(stoneBuilder);
var house = director.ConstructHouse();
house.ShowDetails();
何时使用
当创建一个对象需要多个步骤或配置时,建造者模式特别有用,使构造过程更易于管理。
常见陷阱现实案例
建造者模式通常用于构建复杂的配置,例如软件中的文档或大型表单。
原型模式(Prototype)什么是原型模式?
原型模式通过复制现有对象(即原型)来创建新对象。这个模式在对象创建成本高或过程复杂时特别有用,避免了重复创建新实例的麻烦。
现实生活类比
克隆生物是原型模式的一个恰当类比。与其从头开始创建一个新生物,不如通过克隆现有生物来生成一个相似的个体。
它解决了什么问题?
原型模式解决了对象创建成本昂贵或不合适直接实例化的场景,通过复制现有对象快速生成新实例。
如何在 C# 中实现
以下是一个使用原型模式进行浅拷贝和深拷贝的 C# 示例:
public class PrototypeExample
{
public string Name { get; set; }
public List<string> Data { get; set; }
public PrototypeExample ShallowCopy() => (PrototypeExample)this.MemberwiseClone();
public PrototypeExample DeepCopy()
{
var clone = (PrototypeExample)this.MemberwiseClone();
clone.Data = new List<string>(this.Data);
return clone;
}
}
何时使用
当对象创建成本较高,或者频繁需要基于现有对象创建新对象时,适合使用原型模式。
常见陷阱现实案例
在游戏开发中,原型模式经常用于克隆游戏实体,例如 NPC 或敌人,而不需要从头开始重新创建它们。
创建模式的比较模式使用案例示例
单例
确保一个类只有一个实例。
日志服务,配置
工厂方法
将对象创建与业务逻辑解耦。
创建动物(狗、猫等)
抽象工厂
提供创建相关对象家族的接口。
跨平台UI元素
建造者
逐步构建复杂对象。
建造房屋或配置
原型
通过复制现有对象来创建新对象。
游戏中的克隆实体
创建模式的常见陷阱结论
选择合适的创建模式对于在C#中创建灵活、可维护和可扩展的应用程序至关重要。了解每种模式的优缺点将帮助您在项目中做出明智的决定。尝试不同的模式,以掌握其在实际场景中的使用。
参考文献与进一步阅读