目录
创建型设计模式
创建型设计模式是用于创建对象的一类设计模式,提供了一种更灵活、可复用和可拓展的方式来创建对象
- 工厂方法(Factory Method)
工厂方式提供了一种创建对象的方式,将对象的创建逻辑封装在一个工厂类中,而不是直接在客户端代码中创建对象。工厂方式在实际应用中经常使用,特别是当需要创建的对象在将来可能会有多种不同的实现时,工厂方式提供了一种可扩展的创建对象的方案。
//抽象产品接口 public interface IProduct { void Operation(); } //具体产品类 public class ConcreteProduct : IProduct { public void Operation() { Console.WriteLine("ConcreteProduct"); } } //工厂类 public class ConcreteFactory { public IProduct CreateProduct() { return new ConcreteProduct(); } }
工厂方式的优点包括:
解耦性:客户端代码与具体产品解耦,客户端只需要和抽象产品和工厂交互,无需关心具体的产品实现。
可拓展性:可以通过拓展工厂类和具体的产品来添加新的产品,从而符合开闭原则,无需修改现有代码
封闭性:将对象创建的逻辑封装在工厂类中,客户端无需知道具体的创建细节,减少了代码中的重复代码
- 抽象工厂(Abstract Factory)
抽象工厂提供了一种封装一组具有共同主题的工厂方法的方式。抽象工厂允许客户端通过调用工厂的接口中的方法来创建一系列相关或依赖的对象,而无需知道具体的对象创建逻辑。抽象工厂模式在实际应用中常用于需要创建不同产品族的场景,例如在构建复杂的 UI 界面、创建具有不同数据库的数据访问层等。它提供了一种灵活且可扩展的方式来创建一组相关的对象,并提供了一致的接口与客户端进行交互。
//抽象产品接口 public interfact IProduct { void Operation(); } //具体产品类 public class ConcreteProduct : IProduct { public void Operation() { Console.WriteLine("ConcreteProduct"); } } //抽象工厂接口 public interface IAbstractFactory() { IProduct CreateProduct(); } //具体工厂类 public class ConcreteFactory : IAbstractFactory { public IProduct CreateProduct() { return new ConcreteProduct(); } } public class Program { public static void main(string[] args) { IAbstractFactory factory = new ConcreteFactory(); IProduct product = factory.CreateProduct(); product.Operation(); } }
抽象工厂的优点包括:
封装性:将一组相关的对象创建逻辑封装在抽象工厂接口中,使得客户端代码无需关心具体的对象创建细节
可替换性:通过不同的具体工厂实现,客户端可以在运行时切换不同的产品系列,从而实现了高度的灵活性和可替换性
一致性:抽象工厂保证了一组相关的产品对象是一致的,它们共同遵循同一工厂接口定义的规范
- 单例模式(Singleton)
单例模式保证一个类仅有一个实例,并提供一个访问这个唯一实例的全局访问点public class Singleton { private static Singleton instance; private static readonly object lockObject = new object(); private Singleton() { // 私有化构造函数以防止外部直接实例化对象 } public static Singleton GetInstance() { if (instance == null) { lock (lockObject) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
- 生成器模式(Builder)
生成器模式用于创建复杂对象。该模式将对象的构建过程分步骤进行,并允许按照不同的步骤和配置来构建对象,而不需要暴露对象的内部表示。
// 产品类 public class Product { public string PartA { get; set; } public string PartB { get; set; } public string PartC { get; set; } public void Show() { Console.WriteLine($"PartA: {PartA}"); Console.WriteLine($"PartB: {PartB}"); Console.WriteLine($"PartC: {PartC}"); } } //抽象生成器 public interface IBuilder { void BuildPartA(); void BuildPartB(); void BuildPartC(); Product GetResult(); } //具体生成器 public class ConcreteBuilder : IBuilder { private Product product = new Product(); public void BuildPartA() { product.PartA = "A"; } public void BuildPartB() { product.PartB = "B"; } public void BuildPartC() { product.PartC = "C"; } public Product GetResult() { return product; } } //指导者类 public class Director { public void Construct(IBuilder builder) { builder.BuildPartA(); builder.BuildPartB(); builder.BuildPartC(); } } public class Program { public static void Main(string[] args) { IBuilder builder = new ConcreteBuilder(); Director director = new Director(); director.Construct(builder); Product product = builder.GetResult(); product.Display(); } }
生成器模式的好处是它将复杂对象的构建过程和表示分离,使得我们能够灵活地构建具有不同配置的对象,同时隐藏了对象的实现细节。可以根据不同的需求创建不同的生成器实现,从而创建出符合需求的不同产品。
- 原型模式(Prototype)
原型模型用于创建对象的克隆副本,该模式通过复制现有对象的实例来创建新的对象,而不是通过显式的实例化过程。
原型模式在实际应用中经常用于创建一个复杂对象的副本,从而避免了重新构建这个对象的过程。它常常与工厂方法模式或抽象工厂模式结合使用,以便在克隆时有更多的灵活性。//原型类 public class Prototype : ICloneable { public string Name { get; set; } public int Age { get; set; } public object Clone() { Prototype clone = new Prototype(); clone.Name = this.Name; clone.Age = this.Age; return clone; } }
结构型设计模式
- 适配器模式(Adapter Pattern)
适配器模式允许将一个 类的接口转换为客户端所期望的另一个接口,适配器模式通过包装已有的类来实现接口的转换,使得原本不兼容的类能够一起工作
//目标接口 public interface IAdudioPlayer { void Play(); } //被适配类 public class AudioPlayer { public void PlayMp3() { Console.WriteLine("playMp3"); } } //适配器 public class AudioPlayerAdapter : IAudioPlayer { private AudioPlayer audioPlayer; public AudioPlayerAdapter(AudioPlayer audioPlayer) { this.audioPlayer = audioPlayer; } public void Paly() { Console.WriteLine("Adapter"); audioPlayer.Play(); } } //客户端 public class Client { static void Main(string[] args) { AudioPlayer audioPlayer = new AudioPlayer(); AudioPlayerAdapter adapter = new AudioPlayerAdapter(audioPlayer); adapter.Play(); } }
适配器模式使得不同接口之间的协作成为可能,因为适配器充当了中间层,屏蔽了不同接口的差异性。这样,我们可以方便地将新的类或接口与现有的系统进行集成和交互。
-
桥接模式(Bridge)
桥接模式将抽象部分和实现部分分离,使它们可以独立地变化而互不影响。
//实现化角色 public interface IOperatingSystem { void RunApplication(string appName); } //具体实现化角色 public class Android : IOperatingSystem { public void RunApplication(string appName) { Console.WriteLine("Running" + appName) + "on Android"); } } public class IOS : IOperatingSystem { public void RunApplication(string appName) { Console.WriteLine("Running" + appName + "on IOS"); } } //抽象化角色 public abstract class Phone { protected IOperatingSystem IOperatingSystem; public Phone(IOperatingSystem os) { operatingSystem = os; } public abstract void RunApplication(string appName); } //扩展抽象化角色 public class SamsungPhone : Phone { public SamsungPhone(IOperatingSystem os) : base(os){} public override void RunApplication(string appName) { operatingSystem.RunApplication(appName); } } public class ApplePhone: Phone { public ApplePhone(IOperatingSystem os) : base(os){} public override void RunApplication(string appName) { operatingSystem.RunApplication(appName); } } //客户端 public class Client { static void Main(string[] args) { IOperatingSystem androidOS = new Android(); IOperatingSystem iosOS = new IOS(); Phone samsung = new SamsungPhone(androidOS); Phone iPhone = new ApplePhone(iosOS); samsung.RunApplication("A music Player"); iPhone.RunApplication("Take Phone"); } }
-
组合模式(Composite)
将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性//组件接口 interface IFileSystemComponent { void ShowInfo(); } //叶节点 class FileLeaf : IFileSystemComponent { private string fileName; public FileLeaf(string fileName) { this.fileName = fileName; } public void ShowInfo() { Console.WriteLine("File:" + fileName); } } //组合节点 class DirectoryComposite : IFileSystemComponent { private string directoryName; private List<IFileSystemComponent> components; public DirectoryComposite(string directoryName) { this.directoryName = directoryName; components = new List<IFileSystemComponent>(); } public void AddComponent(IFileSystemComponent component) { components.Add(component); } public void RemoveComponent(IFileSystemComponent component) { components.Remove(component); } public void ShowInfo() { Console.WriteLine("Directory: " + directoryName); foreach (IFileSystemComponent component in components) { component.ShowInfo(); } } } //客户端代码 class Client { static void Main(string[] args) { IFileSystemComponent file1 = new FileLeaf("file1.txt"); IFileSystemComponent file2 = new FileLeaf("file2.txt"); IFileSystemComponent directory1 = new DirectoryComposite("directory1"); IFileSystemComponent directory2 = new DirectoryComposite("directory2"); ((DirectoryComposite)directory1).AddComponent(file1); ((DirectoryComposite)directory2).AddComponent(file2); ((DirectoryComposite)directory2).AddComponent(directory1); directory2.ShowInfo(); } }
通过组合模式,我们可以统一处理文件和文件夹,并以统一的方式操作整个文件系统。这样,我们可以灵活地组织和操作文件系统的结构,而无需关心对象的具体类型。
-
装饰器模式(Decorator)
装饰器模式允许在不改变对象自身结构的情况下,动态地为对象添加额外的行为或责任。通过将对象放入特殊的包装类中,以扩展对象的功能。
//组件接口 interface Text { string getContent(); } //具体组件 class PlainText : Text { private string content; public PlainText(string content) { this.content = content; } public string getContent() { return content; } } //装饰器 abstract class TextDecorator : Text { private Text text; public TextDecorator(Text text) { this.text = text; } public string getContent() { return text.getContent(); } } //具体装饰器 class BoldTextDecorator : TextDecorator { public BoldTextDecorator(Text text) : base(text) {} ; public override striing getContent() { return "<b>" + base.getContent() + "</b>"; } }
使用装饰器模式,可以动态地为对象添加功能,而无需修改原始类的代码。装饰器模式以透明的方式向客户端提供被装饰对象,并且对于客户端而言,装饰器对象和原始对象是可以互换使用的。
-
代理模式(Proxy)
代理模式允许通过创建一个代理对象来控制对另一个对象的访问。代理模式在客户端和被代理对象之间引入了一个中间层,以便在访问对象时进行控制和管理
//抽象主题 public interface Subject { void request(); } //真实主题 public class RealSubject : Subject { private string secret; public RealSubject(string secret) { this.secret = secret; } public void request() { Console.WriteLine("RealSubject"); } } //代理 public class Proxy : Subject { private RealSubject realSubject; private bool enableAccess; public Proxy(string secret) { this.realSubject = new RealSubject(secret); } public void enableAccess() { enabledAccess = true; Console.WriteLine("Proxy : Access enabled"); } public void disableAccess() { enabledAccess = false; Console.WriteLine("Proxy : Access disabled"); } public void request() { if (enabledAccess) { realSubject.request(); } else { Console.WriteLine("Proxy: Access denied."); } } }
通过代理模式,可以在客户端和真实对象之间引入一个中间层,以及控制和管理对真实对象的访问。代理模式提供了一种灵活的方式来控制对对象的访问,并在不改变真实对象的情况下,对其进行增加、修改或控制访问的额外操作。
-
外观模式(Facade)
外观模型旨在提供一个简化的接口,封装了一组复杂的子系统,并对外提供统一的接口。外观模式通过引用一个外观类来隐藏底层操作系统的复杂性,从而简化客户端与子系统之间的交互
//子系统类 public class AudioDecoder { public void decode(string file) { Console.WriteLine("破解音频文件:" + file); } } public class AudioPlayer { public void play() { Console.WriteLine("播放音频"); } } //外观类 public class AudioPlayerFacade { private AudioDecoder decoder; private AudioPlayer player; public void playAudio(string file) { decoder.decode(file); player.play(); } }
-
享元模式(Flyweight)
享元模式旨在通过共享对象来最大程度地减少内存使用和提高性能。通过将对象的状态划分为内部状态和外部状态,并将内部状态共享,在需要时再将外部状态注入到共享对象中
//抽象享元接口 public interface ThreadTask { void execute(); } //具体享元类 public class ConcreteThreadTask : ThreadTask { private string name; public ConcreteThreadTask(string name) { this.name = name; } public void execute() { Console.WriteLine("执行任务:" + name + ",线程ID:" + Thread.CurrentThread().getId()); } } //享元工厂 public class ThreadTaskFactory { private Map<string,ThreadTask> pool; public ThreadTaskFactory() { this.pool = new HashMap<>(); } public ThreadTask getThreadTask(string name) { if(!pool.containsKey(name)) { pool.put(name, new ConcreteThreadTask(name)); } return pool.get(name); } } //客户端代码 public class Client { public static void main(string[] args) { ThreadTaskFactory factory = new ThreadTaskFactory(); ThreadTask task1 = factory.getThreadTask("Task 1"); ThreadTask task2 = factory.getThreadTask("Task 1"); task1.execute(); task2.execute();; Console.WriteLine(task1 == task2); } }
通过享元模式,我们可以实现线程任务对象的共享,避免多次创建相同的任务对象,减少了内存的使用和资源的浪费。
行为型设计模式
- 责任链模式(Chain of Responsibility)
责任链模式使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止
//抽象处理者 public abstract class Approver { protected Approver nextApprover; public void setNextApprover(Approver nextApprover) { this.nextApprover = nextApprover; } public abstract void processRequest(Request request); } //具体处理者 -主任 public class Director : Approver { public void processRequest(Request request) { if(request.getDays() <= 3) { Console.WriteLine("主任审批通过:" + request.getDescription()); } else if(nextApprover != null) { nextApprover.processRequest(request); } } } //具体处理者 -经理 public class Manager : Approver { public void processRequest(Request request) { if(request.getDays() <= 7) { Console.WriteLine("经理审批通过:" + request.getDescription()); } else if(nextApprover != null) { nextApprover.processRequest(request); } } } //具体处理者 -总经理 public class GeneralManager : Approver { public void processRequest(Request request) { if(request.getDays() <= 10) { Console.WriteLine("总经理审批通过:" + request.getDescription()); } else if(nextApprover != null) { Console.WriteLine("申请拒绝:" + request.getDescription()); } } } // 请求类 public class Request { private string description; private int days; public Request(string description, int days) { this.description = description; this.days = days; } public string getDescription() { return description; } public int getDays() { return days; } } // 客户端代码 public class Client { public static void main(String[] args) { Approver director = new Director(); Approver manager = new Manager(); Approver generalManager = new GeneralManager(); director.setNextApprover(manager); manager.setNextApprover(generalManager); Request request1 = new Request("请假 2 天", 2); Request request2 = new Request("请假 5 天", 5); Request request3 = new Request("请假 15 天", 15); director.processRequest(request1); director.processRequest(request2); director.processRequest(request3); } }
使用责任链模式具有以下优点:
解耦请求发送者和接收者:请求发送者不需要知道请求将由哪个具体处理者处理,而具体处理者也不需要知道请求发送者的详细信息。它们只需通过抽象处理者接口进行交互,因此实现了请求发送者和接收者的解耦。
解耦请求发送者和接收者:请求发送者不需要知道请求将由哪个具体处理者处理,而具体处理者也不需要知道请求发送者的详细信息。它们只需通过抽象处理者接口进行交互,因此实现了请求发送者和接收者的解耦。
- 命令模式(Command)
命令模式将请求封装成一个对象,从而使不同 的请求可以参数化其他对象,同时支持请求的排队、记录日志、撤销等操作// 命令接口 public interface ICommand { void Execute(); } // 具体命令 - 打开电视 public class TurnOnTVCommand : ICommand { private TV tv; public TurnOnTVCommand(TV tv) { this.tv = tv; } public void Execute() { tv.TurnOn(); } } // 具体命令 - 关闭电视 public class TurnOffTVCommand : ICommand { private TV tv; public TurnOffTVCommand(TV tv) { this.tv = tv; } public void Execute() { tv.TurnOff(); } } // 接收者类 - 电视 public class TV { public void TurnOn() { Console.WriteLine("电视已打开"); } public void TurnOff() { Console.WriteLine("电视已关闭"); } } // 调用者类 - 遥控器 public class RemoteControl { private ICommand command; public void SetCommand(ICommand command) { this.command = command; } public void PressButton() { command.Execute(); } } // 客户端代码 class Program { static void Main(string[] args) { TV tv = new TV(); ICommand turnOnCommand = new TurnOnTVCommand(tv); ICommand turnOffCommand = new TurnOffTVCommand(tv); RemoteControl remoteControl = new RemoteControl(); remoteControl.SetCommand(turnOnCommand); remoteControl.PressButton(); remoteControl.SetCommand(turnOffCommand); remoteControl.PressButton(); } }
- 中介者模式(Mediator)
中介者模式用于降低多个对象之间的直接耦合,而是通过一个中介者对象来协调它们的交互。在中介者模式中,多个对象之间的通信不再直接发生,而是通过一个中介者对象进行协调。中介者对象包含了多个对象之间的联系和逻辑,负责接收和分发消息,并将消息传递给相应的对象。
// 中介者接口 public interface IMediaPlayerMediator { void PlaySong(string song); void AdjustVolume(int volume); } // 具体中介者类 public class MediaPlayerMediator : IMediaPlayerMediator { private PlayerComponent player; private VolumeComponent volume; private ListBoxComponent listBox; public MediaPlayerMediator(PlayerComponent player, VolumeComponent volume, ListBoxComponent listBox) { this.player = player; this.volume = volume; this.listBox = listBox; // 设置中介者对象 this.player.SetMediator(this); this.volume.SetMediator(this); this.listBox.SetMediator(this); } public void PlaySong(string song) { // 播放器接收到选择的歌曲信息,开始播放 Console.WriteLine($"正在播放歌曲:{song}"); } public void AdjustVolume(int volumeLevel) { // 调节器接收到调节音量的信息,调整音量 Console.WriteLine($"音量已调整为:{volumeLevel}"); } public void SongSelected(string song) { // 列表框接收到歌曲选择的信息,通知播放器开始播放 player.StartPlaying(song); } } // 抽象组件类 public abstract class Component { protected IMediaPlayerMediator mediator; public void SetMediator(IMediaPlayerMediator mediator) { this.mediator = mediator; } } // 播放器组件 public class PlayerComponent : Component { public void StartPlaying(string song) { mediator.PlaySong(song); } } // 音量组件 public class VolumeComponent : Component { public void AdjustVolumeLevel(int volumeLevel) { mediator.AdjustVolume(volumeLevel); } } // 列表框组件 public class ListBoxComponent : Component { public void OnSongSelected(string song) { mediator.SongSelected(song); } } // 客户端代码 class Program { static void Main(string[] args) { PlayerComponent player = new PlayerComponent(); VolumeComponent volume = new VolumeComponent(); ListBoxComponent listBox = new ListBoxComponent(); IMediaPlayerMediator mediator = new MediaPlayerMediator(player, volume, listBox); // 用户选择了一首歌曲 listBox.OnSongSelected("歌曲A"); // 用户调节音量 volume.AdjustVolumeLevel(70); } }
通过中介者模式,我们可以将对象之间的通信逻辑放在中介者对象中,降低了对象之间的耦合度,并实现了集中控制通信的效果。这样,当需要新增或修改通信规则时,只需要修改中介者对象即可,而不会对其他对象产生影响。
- 解释器模式(Interpreter)
解释器模式用于将一种语言的表达式表示为对象,并提供了解释器来解释这些表达式
// 抽象表达式接口 public interface IExpression { int Interpret(Context context); } // 终结符表达式 - 数字表达式 public class NumberExpression : IExpression { private int number; public NumberExpression(int number) { this.number = number; } public int Interpret(Context context) { return number; } } // 非终结符表达式 - 加法表达式 public class AdditionExpression : IExpression { private IExpression leftExpression; private IExpression rightExpression; public AdditionExpression(IExpression leftExpression, IExpression rightExpression) { this.leftExpression = leftExpression; this.rightExpression = rightExpression; } public int Interpret(Context context) { return leftExpression.Interpret(context) + rightExpression.Interpret(context); } } // 上下文类 public class Context { private Dictionary<string, int> variables = new Dictionary<string, int>(); public void SetVariable(string variable, int value) { variables[variable] = value; } public int GetVariable(string variable) { return variables[variable]; } } // 使用示例 class Program { static void Main(string[] args) { Context context = new Context(); // 设置变量值 context.SetVariable("a", 5); context.SetVariable("b", 3); // 创建表达式 IExpression expression = new AdditionExpression( new NumberExpression(context.GetVariable("a")), new NumberExpression(context.GetVariable("b")) ); // 解释表达式并计算结果 int result = expression.Interpret(context); Console.WriteLine("计算结果:" + result); // 输出:计算结果:8 } }
通过迭代器模式,我们可以通过统一的方式遍历不同类型的聚合对象,避免了直接操作聚合对象的细节,提高了代码的灵活性和可维护性。
- 备忘录模式(Memento)
备忘录模式用于保存和恢复对象的内部状态,而不破坏封装性。备忘录模式可将对象恢复到之前的状态,提供了一种简单的撤销/重做机制。
// 备忘录类 public class TextEditorMemento { public string Text { get; private set; } public TextEditorMemento(string text) { Text = text; } } // 发起人类 public class TextEditor { private string text; public string Text { get { return text; } set { text = value; } } public TextEditorMemento Save() { return new TextEditorMemento(text); } public void Restore(TextEditorMemento memento) { text = memento.Text; } } // 负责人类 public class TextEditorHistory { private Stack<TextEditorMemento> history = new Stack<TextEditorMemento>(); public void Save(TextEditorMemento memento) { history.Push(memento); } public TextEditorMemento Undo() { if (history.Count > 0) { return history.Pop(); } return null; } } // 使用示例 class Program { static void Main(string[] args) { TextEditor editor = new TextEditor(); TextEditorHistory history = new TextEditorHistory(); // 编辑文本 editor.Text = "Hello, World!"; Console.WriteLine("Text: " + editor.Text); // 输出:Text: Hello, World! // 保存文本状态 history.Save(editor.Save()); // 修改文本 editor.Text = "Hello, Design Patterns!"; Console.WriteLine("Text: " + editor.Text); // 输出:Text: Hello, Design Patterns! // 撤销操作,恢复到之前的状态 TextEditorMemento previousState = history.Undo(); if (previousState != null) { editor.Restore(previousState); } Console.WriteLine("Text: " + editor.Text); // 输出:Text: Hello, World! } }
通过备忘录模式,我们可以实现对象的状态管理,提供简单的撤销/重做功能,同时保持对象的封装性和灵活性。这种模式可以在很多需要保存对象状态的场景中使用,如文本编辑器、编辑历史、游戏状态等。
- 策略模式(Strategy)
策略(Strategy)设计模式定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。这一模式使得算法可独立于它的客户而变化。
// 策略接口 public interface ISortStrategy { void Sort(int[] array); } // 具体策略类:冒泡排序 public class BubbleSortStrategy : ISortStrategy { public void Sort(int[] array) { Console.WriteLine("使用冒泡排序算法"); // 实现具体的排序算法 } } // 具体策略类:快速排序 public class QuickSortStrategy : ISortStrategy { public void Sort(int[] array) { Console.WriteLine("使用快速排序算法"); // 实现具体的排序算法 } } // 环境类 public class SortContext { private ISortStrategy strategy; public SortContext(ISortStrategy strategy) { this.strategy = strategy; } public void Sort(int[] array) { strategy.Sort(array); } } // 使用示例 class Program { static void Main(string[] args) { int[] array = { 5, 2, 8, 7, 1 }; SortContext context; // 使用冒泡排序策略 context = new SortContext(new BubbleSortStrategy()); context.Sort(array); // 使用快速排序策略 context = new SortContext(new QuickSortStrategy()); context.Sort(array); } }
策略模式通过定义一个策略接口或抽象类,将不同的算法或策略封装到具体的策略类中。然后,在客户端只需要依赖于策略接口,根据需要选择合适的策略类,从而实现运行时的算法替换和扩展。
- 观察者模式(Observer)
观察者(Observer)设计模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
// 主题接口 public interface ISubject { void RegisterObserver(IObserver observer); void RemoveObserver(IObserver observer); void NotifyObservers(); } // 观察者接口 public interface IObserver { void Update(float temperature, float humidity, float pressure); } // 具体主题:气象站 public class WeatherStation : ISubject { private List<IObserver> observers = new List<IObserver>(); private float temperature; private float humidity; private float pressure; public void RegisterObserver(IObserver observer) { observers.Add(observer); } public void RemoveObserver(IObserver observer) { observers.Remove(observer); } public void NotifyObservers() { foreach (IObserver observer in observers) { observer.Update(temperature, humidity, pressure); } } public void SetMeasurements(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; this.pressure = pressure; NotifyObservers(); } } // 具体观察者:布告板 public class DisplayBoard : IObserver { public void Update(float temperature, float humidity, float pressure) { // 更新布告板显示 } } // 使用示例 class Program { static void Main(string[] args) { WeatherStation weatherStation = new WeatherStation(); DisplayBoard displayBoard = new DisplayBoard(); // 注册观察者 weatherStation.RegisterObserver(displayBoard); // 设置气象数据,并触发通知 weatherStation.SetMeasurements(25.5f, 65.2f, 1013.2f); } }
观察者模式通过定义了一个被观察者(通常称为主题或主体)和多个观察者的接口,使得观察者对象可以注册、取消注册和接收通知。当被观察者的状态发生变化时,它会主动通知所有已注册的观察者进行相应的更新。
- 状态模式(State)
状态模式用于在对象内部状态改变时改变其行为。状态模式将对象的各种状态封装成独立的类,并将对象的行为委托给当前状态类,以实现状态间的切换和相应行为的变化。
// 状态接口 public interface ITrafficLightState { void Handle(); } // 具体状态类:红灯状态 public class RedLightState : ITrafficLightState { public void Handle() { Console.WriteLine("红灯停"); // 延时一段时间后切换到下一个状态 Thread.Sleep(2000); } } // 具体状态类:绿灯状态 public class GreenLightState : ITrafficLightState { public void Handle() { Console.WriteLine("绿灯行"); // 延时一段时间后切换到下一个状态 Thread.Sleep(2000); } } // 具体状态类:黄灯状态 public class YellowLightState : ITrafficLightState { public void Handle() { Console.WriteLine("黄灯等待"); // 延时一段时间后切换到下一个状态 Thread.Sleep(2000); } } // 环境类:交通信号灯 public class TrafficLight { private ITrafficLightState currentState; public TrafficLight() { currentState = new RedLightState(); } public void SetState(ITrafficLightState state) { currentState = state; } public void ChangeState() { if (currentState is RedLightState) { SetState(new GreenLightState()); } else if (currentState is GreenLightState) { SetState(new YellowLightState()); } else if (currentState is YellowLightState) { SetState(new RedLightState()); } } public void Run() { while (true) { currentState.Handle(); ChangeState(); } } } // 使用示例 class Program { static void Main(string[] args) { TrafficLight trafficLight = new TrafficLight(); trafficLight.Run(); } }
通过状态模式,对象的行为可以根据内部状态的改变而变化,避免了大量的条件语句或 switch 语句。状态模式提供了一种清晰的方式来组织对象的状态和行为,并通过封装每个状态的行为,使得状态间的切换更加灵活和可维护。状态模式常用于具有多种状态转换的场景,如订单状态、工作流程等。
- 访问者模式(Visitor)
访问者模式用于在不改变已有类的情况下定义新的操作,并将其封装在访问者对象中。访问者模式将数据结构和作用于数据上的操作解耦,使得操作可以独立变化。
访问者模式的核心思想是将操作封装在访问者中,通过让元素接受访问者的方式来触发操作。这样一来,我们可以方便地增加新的操作,而无需修改元素类的结构。// 访问者接口 public interface IVisitor { void Visit(Fruit fruit); void Visit(Book book); } // 具体访问者:结账访问者 public class CheckoutVisitor : IVisitor { public void Visit(Fruit fruit) { Console.WriteLine($"结账:购买了 {fruit.Name},价格为 {fruit.Price} 元"); } public void Visit(Book book) { Console.WriteLine($"结账:购买了 {book.Name},价格为 {book.Price} 元"); } } // 元素接口 public interface IElement { void Accept(IVisitor visitor); } // 具体元素:水果 public class Fruit : IElement { public string Name { get; set; } public decimal Price { get; set; } public Fruit(string name, decimal price) { Name = name; Price = price; } public void Accept(IVisitor visitor) { visitor.Visit(this); } } // 具体元素:图书 public class Book : IElement { public string Name { get; set; } public decimal Price { get; set; } public Book(string name, decimal price) { Name = name; Price = price; } public void Accept(IVisitor visitor) { visitor.Visit(this); } } // 对象结构:购物车 public class ShoppingCart { private List<IElement> items; public ShoppingCart() { items = new List<IElement>(); } public void AddItem(IElement item) { items.Add(item); } public void AcceptVisitor(IVisitor visitor) { foreach (var item in items) { item.Accept(visitor); } } } // 使用示例 class Program { static void Main(string[] args) { ShoppingCart cart = new ShoppingCart(); cart.AddItem(new Fruit("Apple", 2.5m)); cart.AddItem(new Fruit("Banana", 1.8m)); cart.AddItem(new Book("Design Patterns", 59.9m)); CheckoutVisitor visitor = new CheckoutVisitor(); cart.AcceptVisitor(visitor); } }
- 模板方法模式(Template Method)
模板方法(Template Method)设计模式定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重新定义算法的某些特定步骤。
// 抽象类:饮料模板 public abstract class BeverageTemplate { // 制作饮料的步骤 public void MakeBeverage() { BoilWater(); Brew(); PourInCup(); AddCondiments(); } protected abstract void Brew(); // 冲泡 protected abstract void AddCondiments(); // 加调料 private void BoilWater() { Console.WriteLine("烧水"); } private void PourInCup() { Console.WriteLine("倒入杯中"); } } // 具体类:制作咖啡 public class Coffee : BeverageTemplate { protected override void Brew() { Console.WriteLine("用沸水冲泡咖啡粉"); } protected override void AddCondiments() { Console.WriteLine("加入糖和牛奶"); } } // 具体类:制作茶 public class Tea : BeverageTemplate { protected override void Brew() { Console.WriteLine("用沸水冲泡茶叶"); } protected override void AddCondiments() { Console.WriteLine("加入柠檬"); } } // 使用示例 class Program { static void Main(string[] args) { BeverageTemplate coffee = new Coffee(); coffee.MakeBeverage(); Console.WriteLine(); BeverageTemplate tea = new Tea(); tea.MakeBeverage(); } }
模板模式的核心思想是定义一个抽象类来表示算法的骨架,其中包含一些公共的方法和抽象的待实现的方法。具体的子类继承抽象类,并实现其中的抽象方法,以完成具体的步骤