# 使用c#實現23種常見的設計模式 設計模式通常分為三個主要類別: - 創建型模式 - 結構型模式 - 行為型模式。 這些模式是用於解決常見的對象導向設計問題的最佳實踐。 以下是23種常見的設計模式並且提供`c#代碼案例`: ## 創建型模式: ### 1. 單例模式(Singleton) ``` ...
使用c#實現23種常見的設計模式
設計模式通常分為三個主要類別:
-
創建型模式
-
結構型模式
-
行為型模式。
這些模式是用於解決常見的對象導向設計問題的最佳實踐。
以下是23種常見的設計模式並且提供c#代碼案例
:
創建型模式:
1. 單例模式(Singleton)
public sealed class Singleton
{
//創建一個只讀的靜態Singleton實例
private static readonly Singleton instance = new Singleton();
// 記錄Singleton的創建次數
private static int instanceCounter = 0;
// 單例實例的公共訪問點
public static Singleton Instance
{
get
{
return instance;
}
}
// 私有構造函數
private Singleton()
{
instanceCounter++;
Console.WriteLine("Instances Created " + instanceCounter);
}
// 在此處添加其他的Singleton類方法
public void LogMessage(string message)
{
Console.WriteLine("Message: " + message);
}
}
在這個例子中,我們有一個名為Singleton
的類,它有一個私有的構造函數和一個靜態的只讀屬性Instance
,用於訪問Singleton
類的唯一實例。我們還有一個LogMessage
方法,用於模擬Singleton
類的某個行為。
以下是一個使用這個Singleton
類的控制台應用程式:
class Program
{
static void Main(string[] args)
{
Singleton fromEmployee = Singleton.Instance;
fromEmployee.LogMessage("Message from Employee");
Singleton fromBoss = Singleton.Instance;
fromBoss.LogMessage("Message from Boss");
Console.ReadLine();
}
}
2. 工廠方法模式(Factory Method)
工廠方法模式是一種創建型設計模式,它提供了一種創建對象的介面,但允許子類決定實例化哪個類。工廠方法讓類的實例化推遲到子類中進行。
下麵是一個使用C#實現的工廠方法模式的簡單示例:
// 抽象產品
public interface IProduct
{
string Operation();
}
// 具體產品A
public class ProductA : IProduct
{
public string Operation()
{
return "{Result of ProductA}";
}
}
// 具體產品B
public class ProductB : IProduct
{
public string Operation()
{
return "{Result of ProductB}";
}
}
// 抽象創建者
public abstract class Creator
{
public abstract IProduct FactoryMethod();
}
// 具體創建者A
public class CreatorA : Creator
{
public override IProduct FactoryMethod()
{
return new ProductA();
}
}
// 具體創建者B
public class CreatorB : Creator
{
public override IProduct FactoryMethod()
{
return new ProductB();
}
}
以上代碼中定義了兩個產品ProductA
和ProductB
,這兩個產品都實現了IProduct
介面。接著我們有兩個Creator類,CreatorA
和CreatorB
,它們都繼承自抽象基類Creator
。CreatorA
工廠創建ProductA
,CreatorB
工廠創建ProductB
。
以下是一個使用這些工廠和產品的示例:
class Program
{
static void Main(string[] args)
{
// 創建工廠對象
Creator creatorA = new CreatorA();
Creator creatorB = new CreatorB();
// 通過工廠方法創建產品對象
IProduct productA = creatorA.FactoryMethod();
IProduct productB = creatorB.FactoryMethod();
// 列印結果
Console.WriteLine("ProductA says: " + productA.Operation());
Console.WriteLine("ProductB says: " + productB.Operation());
Console.ReadLine();
}
}
當你運行這個程式時,它會顯示出ProductA
和ProductB
的Operation
方法返回的結果。這說明我們已經成功地使用工廠方法模式創建了產品實例。每個工廠類決定了它創建哪個產品的實例。這種方式使得客戶端代碼不需要直接實例化產品類,而只需要依賴工廠介面,增加了程式的靈活性。
3. 抽象工廠模式(Abstract Factory)
抽象工廠模式是一種創建型設計模式,它提供了一種介面,用於創建相關或依賴對象的系列,而不指定這些對象的具體類。在這個模式中,客戶端通過他們的抽象介面使用類,允許該模式在不影響客戶端的情況下替換實現類。
以下是一個簡單的抽象工廠模式的C#實現:
// 抽象產品:動物
public interface IAnimal
{
string Speak();
}
// 具體產品:狗
public class Dog : IAnimal
{
public string Speak()
{
return "Bark Bark";
}
}
// 具體產品:貓
public class Cat : IAnimal
{
public string Speak()
{
return "Meow Meow";
}
}
// 抽象工廠
public abstract class IAnimalFactory
{
public abstract IAnimal CreateAnimal();
}
// 具體工廠:狗工廠
public class DogFactory : IAnimalFactory
{
public override IAnimal CreateAnimal()
{
return new Dog();
}
}
// 具體工廠:貓工廠
public class CatFactory : IAnimalFactory
{
public override IAnimal CreateAnimal()
{
return new Cat();
}
}
以上代碼定義了兩種動物Dog
和Cat
,它們都實現了IAnimal
介面。然後我們有兩個工廠類,DogFactory
和CatFactory
,它們都繼承自IAnimalFactory
。DogFactory
生產Dog
,而CatFactory
生產Cat
。
以下是一個使用這些工廠和產品的示例:
class Program
{
static void Main(string[] args)
{
// 創建工廠
IAnimalFactory dogFactory = new DogFactory();
IAnimalFactory catFactory = new CatFactory();
// 使用工廠創建產品
IAnimal dog = dogFactory.CreateAnimal();
IAnimal cat = catFactory.CreateAnimal();
// 列印結果
Console.WriteLine("Dog says: " + dog.Speak());
Console.WriteLine("Cat says: " + cat.Speak());
Console.ReadLine();
}
}
當你運行這個程式時,會列印出Dog和Cat的Speak方法的結果,這顯示了我們已經成功地使用了抽象工廠模式創建了產品實例。這種方式使得客戶端代碼不需要直接實例化產品類,而只需要依賴工廠介面,增加了程式的靈活性和擴展性。
4. 建造者模式(Builder)
建造者模式是一種創建型設計模式,它提供了一種創建對象的介面,但是允許使用相同的構建過程來創建不同的產品。
以下是在C#中實現建造者模式的一個簡單示例:
// 產品
public class Car
{
public string Engine { get; set; }
public string Wheels { get; set; }
public string Doors { get; set; }
}
// 建造者抽象類
public abstract class CarBuilder
{
protected Car car;
public void CreateNewCar()
{
car = new Car();
}
public Car GetCar()
{
return car;
}
public abstract void SetEngine();
public abstract void SetWheels();
public abstract void SetDoors();
}
// 具體建造者
public class FerrariBuilder : CarBuilder
{
public override void SetEngine()
{
car.Engine = "V8";
}
public override void SetWheels()
{
car.Wheels = "18 inch";
}
public override void SetDoors()
{
car.Doors = "2";
}
}
// 指揮者
public class Director
{
public Car Construct(CarBuilder carBuilder)
{
carBuilder.CreateNewCar();
carBuilder.SetEngine();
carBuilder.SetWheels();
carBuilder.SetDoors();
return carBuilder.GetCar();
}
}
以上代碼中,Car
是我們要創建的產品,CarBuilder
是抽象的建造者,定義了製造一個產品所需要的各個步驟,FerrariBuilder
是具體的建造者,實現了CarBuilder
定義的所有步驟,Director
是指揮者,它告訴建造者應該按照什麼順序去執行哪些步驟。
以下是一個使用這個建造者模式的示例:
class Program
{
static void Main(string[] args)
{
Director director = new Director();
CarBuilder builder = new FerrariBuilder();
Car ferrari = director.Construct(builder);
Console.WriteLine($"Engine: {ferrari.Engine}, Wheels: {ferrari.Wheels}, Doors: {ferrari.Doors}");
Console.ReadLine();
}
}
當你運行這個程式時,會看到我們已經成功地創建了一個Car
實例,它的各個部分是按照FerrariBuilder
所定義的方式創建的。這說明我們使用建造者模式成功地將一個複雜對象的構造過程解耦,使得同樣的構造過程可以創建不同的表示。
5. 原型模式(Prototype)
原型模式是一種創建型設計模式,它實現了一個原型介面,該介面用於創建當前對象的克隆。當直接創建對象的代價比較大時,則採用這種模式。例如,一個對象需要在一個高代價的資料庫操作後被創建。
以下是在C#中實現原型模式的一個簡單示例:
// 抽象原型
public interface IPrototype
{
IPrototype Clone();
}
// 具體原型
public class ConcretePrototype : IPrototype
{
public string Name { get; set; }
public int Value { get; set; }
public IPrototype Clone()
{
// 實現深拷貝
return (ConcretePrototype)this.MemberwiseClone(); // Clones the concrete object.
}
}
以上代碼定義了一個ConcretePrototype
類,它實現了IPrototype
介面。介面定義了一個Clone
方法,用於複製對象。在ConcretePrototype
類中,我們使用了MemberwiseClone
方法來創建一個新的克隆對象。
以下是一個使用原型模式的示例:
class Program
{
static void Main(string[] args)
{
ConcretePrototype prototype = new ConcretePrototype();
prototype.Name = "Original";
prototype.Value = 10;
Console.WriteLine("Original instance: " + prototype.Name + ", " + prototype.Value);
ConcretePrototype clone = (ConcretePrototype)prototype.Clone();
Console.WriteLine("Cloned instance: " + clone.Name + ", " + clone.Value);
Console.ReadLine();
}
}
在這個例子中,我們創建了一個ConcretePrototype
對象,併為其屬性賦值,然後我們調用Clone
方法創建了一個新的ConcretePrototype
對象。當我們運行這個程式時,會看到原始對象和克隆對象的屬性是相同的,這表明我們已經成功地克隆了一個對象。
執行流程如下:
- 創建一個具體的原型對象,為其屬性賦值。
- 調用原型對象的
Clone
方法,創建一個新的對象,該對象的屬性與原型對象的屬性相同。 - 列印原型對象和克隆對象的屬性,驗證它們是否相同。
結構型模式: 6. 適配器模式(Adapter)
1. 橋接模式(Bridge)
橋接模式是一種結構型設計模式,用於將抽象部分與其實現部分分離,使它們都可以獨立地變化。
以下是在C#中實現橋接模式的一個簡單示例:
// 實現類介面
public interface IImplementor
{
void OperationImp();
}
// 具體實現類A
public class ConcreteImplementorA : IImplementor
{
public void OperationImp()
{
Console.WriteLine("Concrete Implementor A");
}
}
// 具體實現類B
public class ConcreteImplementorB : IImplementor
{
public void OperationImp()
{
Console.WriteLine("Concrete Implementor B");
}
}
// 抽象類
public abstract class Abstraction
{
protected IImplementor implementor;
public Abstraction(IImplementor implementor)
{
this.implementor = implementor;
}
public virtual void Operation()
{
implementor.OperationImp();
}
}
// 擴充的抽象類
public class RefinedAbstraction : Abstraction
{
public RefinedAbstraction(IImplementor implementor) : base(implementor) { }
public override void Operation()
{
Console.WriteLine("Refined Abstraction is calling implementor's method:");
base.Operation();
}
}
在這個代碼中,Abstraction
是抽象類,它有一個IImplementor
介面的實例,通過這個實例調用實現類的方法。RefinedAbstraction
是擴充的抽象類,它繼承自Abstraction
。ConcreteImplementorA
和ConcreteImplementorB
是實現類,它們實現了IImplementor
介面。
以下是一個使用這個模式的示例:
class Program
{
static void Main(string[] args)
{
IImplementor implementorA = new ConcreteImplementorA();
Abstraction abstractionA = new RefinedAbstraction(implementorA);
abstractionA.Operation();
IImplementor implementorB = new ConcreteImplementorB();
Abstraction abstractionB = new RefinedAbstraction(implementorB);
abstractionB.Operation();
Console.ReadLine();
}
}
在這個例子中,我們創建了兩個實現類的實例,然後創建了兩個抽象類的實例,每個抽象類的實例都有一個實現類的實例。當我們調用抽象類的Operation
方法時,它會調用實現類的OperationImp
方法。
執行流程如下:
- 創建實現類的實例。
- 創建抽象類的實例,抽象類的實例有一個實現類的實例。
- 調用抽象類的
Operation
方法,該方法會調用實現類的OperationImp
方法。
2. 組合模式(Composite)
組合模式(Composite pattern)是一種結構型設計模式,它可以使你將對象組合成樹形結構,並且能像使用獨立對象一樣使用它們。這種模式的主要目的是使單個對象和組合對象具有一致性。
以下是在C#中實現組合模式的一個簡單示例:
// 抽象組件類
public abstract class Component
{
protected string name;
public Component(string name)
{
this.name = name;
}
public abstract void Add(Component c);
public abstract void Remove(Component c);
public abstract void Display(int depth);
}
// 葉節點類
public class Leaf : Component
{
public Leaf(string name) : base(name) { }
public override void Add(Component c)
{
Console.WriteLine("Cannot add to a leaf");
}
public override void Remove(Component c)
{
Console.WriteLine("Cannot remove from a leaf");
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
}
}
// 構件容器類
public class Composite : Component
{
private List<Component> _children = new List<Component>();
public Composite(string name) : base(name) { }
public override void Add(Component component)
{
_children.Add(component);
}
public override void Remove(Component component)
{
_children.Remove(component);
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
// 顯示每個節點的子節點
foreach (Component component in _children)
{
component.Display(depth + 2);
}
}
}
在這個代碼中,Component
是組件抽象類,它有一個名字,並定義了添加、刪除和顯示操作。Leaf
是葉子節點,它實現了Component
的操作。Composite
是組件容器,它可以添加、刪除和顯示其子節點。
以下是一個使用這個模式的示例:
class Program
{
static void Main(string[] args)
{
Composite root = new Composite("root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));
Composite comp = new Composite("Composite X");
comp.Add(new Leaf("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));
root.Add(comp);
Composite comp2 = new Composite("Composite XY");
comp2.Add(new Leaf("Leaf XYA"));
comp2.Add(new Leaf("Leaf XYB"));
comp.Add(comp2);
root.Add(new Leaf("Leaf C"));
// 在組合中添加和刪除
Leaf leaf = new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);
// 顯示樹形結構
root.Display(1);
Console.ReadLine();
}
}
在這個例子中,我們創建了一個根節點,併在其中添加了兩個葉子節點。然後我們創建了一個複合節點,併在其中添加了兩個葉子節點,然後我們把複合節點添加到根節點中。我們還在複合節點中添加了另一個複合節點。最後,我們又在根節點中添加和刪除了一個葉子節點,然後顯示了樹的結構。
執行流程如下:
- 創建組合和葉子對象。
- 通過調用組合對象的
Add
方法將葉子對象和其他組合對象添加到組合對象中。 - 通過調用組合對象的
Remove
方法將葉子對象從組合對象中移除。 - 調用組合對象的
Display
方法顯示組合對象的結構。
3. 裝飾模式(Decorator)
裝飾模式是一種結構型設計模式,它允許在運行時動態地將功能添加到對象中,這種模式提供了比繼承更有彈性的解決方案。
以下是在C#中實現裝飾模式的一個簡單示例:
// 抽象組件
public abstract class Component
{
public abstract string Operation();
}
// 具體組件
public class ConcreteComponent : Component
{
public override string Operation()
{
return "ConcreteComponent";
}
}
// 抽象裝飾器
public abstract class Decorator : Component
{
protected Component component;
public Decorator(Component component)
{
this.component = component;
}
public override string Operation()
{
if (component != null)
{
return component.Operation();
}
else
{
return string.Empty;
}
}
}
// 具體裝飾器A
public class ConcreteDecoratorA : Decorator
{
public ConcreteDecoratorA(Component comp) : base(comp) { }
public override string Operation()
{
return $"ConcreteDecoratorA({base.Operation()})";
}
}
// 具體裝飾器B
public class ConcreteDecoratorB : Decorator
{
public ConcreteDecoratorB(Component comp) : base(comp) { }
public override string Operation()
{
return $"ConcreteDecoratorB({base.Operation()})";
}
}
在這個代碼中,Component
是一個抽象組件,它定義了一個Operation
方法。ConcreteComponent
是具體組件,它實現了Component
的Operation
方法。Decorator
是一個抽象裝飾器,它包含一個Component
對象,並重寫了Operation
方法。ConcreteDecoratorA
和ConcreteDecoratorB
是具體的裝飾器,它們繼承了Decorator
並重寫了Operation
方法,以添加新的功能。
以下是一個使用這個模式的示例:
class Program
{
static void Main(string[] args)
{
// 基本組件
Component component = new ConcreteComponent();
Console.WriteLine("Basic Component: " + component.Operation());
// 裝飾後的組件
Component decoratorA = new ConcreteDecoratorA(component);
Console.WriteLine("A Decorated: " + decoratorA.Operation());
Component decoratorB = new ConcreteDecoratorB(decoratorA);
Console.WriteLine("B Decorated: " + decoratorB.Operation());
Console.ReadLine();
}
}
在這個例子中,我們首先創建了一個ConcreteComponent
對象,並調用它的Operation
方法。然後我們創建了一個ConcreteDecoratorA
對象,它裝飾了ConcreteComponent
,並調用它的Operation
方法。最後,我們創建了一個ConcreteDecoratorB
對象,它裝飾了ConcreteDecoratorA
,並調用它的Operation
方法。這樣,我們就可以在運行時動態地添加功能。
執行流程如下:
- 創建一個具體組件對象並調用其操作。
- 創建一個裝飾器對象,該對象裝飾了具體組件,並調用其操作。在操作中,裝飾器首先調用具體組件的操作,然後執行額外的操作。
- 創建另一個裝飾器對象,裝飾前一個裝飾器,並調用其操作。在操作中,這個裝飾器首先調用前一個裝飾器的操作,然後執行額外的操作。
4. 外觀模式(Facade)
外觀模式是一種結構型設計模式,提供了一個統一的介面,用來訪問子系統中的一群介面。外觀模式定義了一個高層介面,讓子系統更容易使用。
以下是在C#中實現外觀模式的一個簡單示例:
// 子系統A
public class SubSystemA
{
public string OperationA()
{
return "SubSystemA, OperationA\n";
}
}
// 子系統B
public class SubSystemB
{
public string OperationB()
{
return "SubSystemB, OperationB\n";
}
}
// 子系統C
public class SubSystemC
{
public string OperationC()
{
return "SubSystemC, OperationC\n";
}
}
// 外觀類
public class Facade
{
private SubSystemA a = new SubSystemA();
private SubSystemB b = new SubSystemB();
private SubSystemC c = new SubSystemC();
public string OperationWrapper()
{
string result = "Facade initializes subsystems:\n";
result += a.OperationA();
result += b.OperationB();
result += c.OperationC();
return result;
}
}
在這個代碼中,SubSystemA
,SubSystemB
和SubSystemC
都是子系統,每個子系統都有一個操作。Facade
是一個外觀類,它封裝了對子系統的操作,提供了一個統一的介面。
以下是一個使用這個模式的示例:
class Program
{
static void Main(string[] args)
{
Facade facade = new Facade();
Console.WriteLine(facade.OperationWrapper());
Console.ReadLine();
}
}
在這個例子中,我們創建了一個Facade
對象,並調用了它的OperationWrapper
方法。這個方法封裝了對子系統的操作,使得客戶端可以不直接操作子系統,而是通過外觀類操作子系統。
執行流程如下:
-
創建一個外觀對象。
-
通過調用外觀對象的方法,間接地操作子系統。
-
子系統的操作被封裝在外觀對象的方法中,客戶端不需要直接操作子系統。
5. 享元模式(Flyweight)
享元模式(Flyweight Pattern)是一種結構型設計模式,該模式主要用於減少創建對象的數量,以減少記憶體占用和提高性能。這種類型的設計模式屬於結構型模式,它提供了一種減少對象數量從而改善應用所需的對象結構的方式。
以下是在C#中實現享元模式的一個簡單示例:
// 享元類
public class Flyweight
{
private string intrinsicState;
// 構造函數
public Flyweight(string intrinsicState)
{
this.intrinsicState = intrinsicState;
}
// 業務方法
public void Operation(string extrinsicState)
{
Console.WriteLine($"Intrinsic State = {intrinsicState}, Extrinsic State = {extrinsicState}");
}
}
// 享元工廠類
public class FlyweightFactory
{
private Dictionary<string, Flyweight> flyweights = new Dictionary<string, Flyweight>();
public Flyweight GetFlyweight(string key)
{
if (!flyweights.ContainsKey(key))
{
flyweights[key] = new Flyweight(key);
}
return flyweights[key];
}
public int GetFlyweightCount()
{
return flyweights.Count;
}
}
在這個代碼中,Flyweight
是享元類,它有一個內在狀態intrinsicState
,這個狀態是不變的。FlyweightFactory
是享元工廠類,它維護了一個享元對象的集合。
以下是一個使用這個模式的示例:
class Program
{
static void Main(string[] args)
{
FlyweightFactory factory = new FlyweightFactory();
Flyweight flyweightA = factory.GetFlyweight("A");
flyweightA.Operation("A operation");
Flyweight flyweightB = factory.GetFlyweight("B");
flyweightB.Operation("B operation");
Flyweight flyweightC = factory.GetFlyweight("A");
flyweightC.Operation("C operation");
Console.WriteLine($"Total Flyweights: {factory.GetFlyweightCount()}");
Console.ReadLine();
}
}
在這個例子中,我們創建了一個FlyweightFactory
對象,並通過它創建了兩個享元對象。註意,當我們試圖創建第三個享元對象時,工廠實際上返回了第一個享元對象的引用,因為這兩個對象的內在狀態是相同的。
執行流程如下:
- 創建一個享元工廠對象。
- 通過享元工廠獲取享元對象。如果對象已經存在,則返回現有對象;否則,創建新對象。
- 執行享元對象的操作。
- 顯示當前享元對象的數量。
6. 代理模式(Proxy)
代理模式是一種結構型設計模式,它提供了一個對象代替另一個對象來控制對它的訪問。代理對象可以在客戶端和目標對象之間起到中介的作用,並添加其他的功能。
以下是在C#中實現代理模式的一個簡單示例:
// 抽象主題介面
public interface ISubject
{
void Request();
}
// 真實主題
public class RealSubject : ISubject
{
public void Request()
{
Console.WriteLine("RealSubject: Handling Request.");
}
}
// 代理
public class Proxy : ISubject
{
private RealSubject _realSubject;
public Proxy(RealSubject realSubject)
{
this._realSubject = realSubject;
}
public void Request()
{
if (this.CheckAccess())
{
this._realSubject.Request();
this.LogAccess();
}
}
public bool CheckAccess()
{
// 檢查是否有許可權訪問
Console.WriteLine("Proxy: Checking access prior to firing a real request.");
return true;
}
public void LogAccess()
{
// 記錄請求
Console.WriteLine("Proxy: Logging the time of request.");
}
}
在這個代碼中,ISubject
是一個介面,定義了Request
方法。RealSubject
是實現了ISubject
介面的類,Proxy
是代理類,它也實現了ISubject
介面,並持有一個RealSubject
對象的引用。
以下是一個使用這個模式的示例:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Client: Executing the client code with a real subject:");
RealSubject realSubject = new RealSubject();
realSubject.Request();
Console.WriteLine();
Console.WriteLine("Client: Executing the same client code with a proxy:");
Proxy proxy = new Proxy(realSubject);
proxy.Request();
Console.ReadLine();
}
}
在這個例子中,我們首先直接調用了RealSubject
的Request
方法,然後我們通過代理調用了相同的方法。註意,在通過代理調用Request
方法時,代理還執行了其他的操作,如檢查訪問許可權和記錄日誌。
執行流程如下:
- 創建一個真實主題對象,並直接調用其
Request
方法。 - 創建一個代理對象,代理對象包含一個真實主題的引用。
- 通過代理對象調用
Request
方法。在這個方法中,代理首先檢查訪問許可權,然後調用真實主題的Request
方法,最後記錄日誌。
行為型模式: 13. 責任鏈模式(Chain of Responsibility)
1. 命令模式(Command)
命令模式(Command Pattern)是一種數據驅動的設計模式,它屬於行為型模式。在命令模式中,請求在對象中封裝成為一個操作或行為,這些請求被送到調用對象,調用對象尋找可以處理該命令的合適的對象,並把命令直接送達到對應的對象,該對象會執行這些命令。
以下是在C#中實現命令模式的一個簡單示例:
// 命令介面
public interface ICommand
{
void Execute();
}
// 具體命令類
public class ConcreteCommand : ICommand
{
private Receiver receiver;
public ConcreteCommand(Receiver receiver)
{
this.receiver = receiver;
}
public void Execute()
{
receiver.Action();
}
}
// 接收者類
public class Receiver
{
public void Action()
{
Console.WriteLine("Receiver performs an action");
}
}
// 調用者或發送者類
public class Invoker
{
private ICommand command;
public void SetCommand(ICommand command)
{
this.command = command;
}
public void ExecuteCommand()
{
command.Execute();
}
}
在這個代碼中,ICommand
是命令介面,定義了Execute
方法。ConcreteCommand
是具體的命令類,它實現了ICommand
介面,並持有一個Receiver
對象的引用。Invoker
是調用者或發送者類,它持有一個ICommand
對象的引用,並可以通過SetCommand
方法設置命令,通過ExecuteCommand
方法執行命令。
以下是一個使用這個模式的示例:
class Program
{
static void Main(string[] args)
{
Receiver receiver = new Receiver();
ICommand command = new ConcreteCommand(receiver);
Invoker invoker = new Invoker();
invoker.SetCommand(command);
invoker.ExecuteCommand();
Console.ReadLine();
}
}
在這個例子中,我們創建了一個Receiver
對象、一個ConcreteCommand
對象和一個Invoker
對象。然後我們通過Invoker
的SetCommand
方法設置了命令,並通過ExecuteCommand
方法執行了命令。
執行流程如下:
- 創建一個接收者對象。
- 創建一個具體命令對象,並將接收者對象傳遞給它。
- 創建一個調用者或發送者對象。
- 通過調用者對象的
SetCommand
方法設置命令。 - 通過調用者對象的
ExecuteCommand
方法執行命令。
2. 解釋器模式(Interpreter)
解釋器模式(Interpreter Pattern)是一種行為型設計模式,用於解決一些固定語法格式的需求。它定義瞭如何在語言中表示和解析語法。
以下是在C#中實現解釋器模式的一個簡單示例:
// 抽象表達式
public interface IExpression
{
bool Interpret(string context);
}
// 終結符表達式
public class TerminalExpression : IExpression
{
private string data;
public TerminalExpression(string data)
{
this.data = data;
}
public bool Interpret(string context)
{
if (context.Contains(data))
{
return true;
}
return false;
}
}
// 非終結符表達式
public class OrExpression : IExpression
{
private IExpression expr1 = null;
private IExpression expr2 = null;
public OrExpression(IExpression expr1, IExpression expr2)
{
this.expr1 = expr1;
this.expr2 = expr2;
}
public bool Interpret(string context)
{
return expr1.Interpret(context) || expr2.Interpret(context);
}
}
在這個代碼中,IExpression
是抽象表達式,定義了Interpret
方法。TerminalExpression
是終結符表達式,它實現了IExpression
介面。OrExpression
是非終結符表達式,它也實現了IExpression
介面。
以下是一個使用這個模式的示例:
class Program
{
static void Main(string[] args)
{
IExpression isMale = GetMaleExpression();
IExpression isMarriedWoman = GetMarriedWomanExpression();
Console.WriteLine($"John is male? {isMale.Interpret("John")}");
Console.WriteLine($"Julie is a married women? {isMarriedWoman.Interpret("Married Julie")}");
Console.ReadLine();
}
// 規則:Robert 和 John 是男性
public static IExpression GetMaleExpression()
{
IExpression robert = new TerminalExpression("Robert");
IExpression john = new TerminalExpression("John");
return new OrExpression(robert, john);
}
// 規則:Julie 是一個已婚的女性
public static IExpression GetMarriedWomanExpression()
{
IExpression julie = new TerminalExpression("Julie");
IExpression married = new TerminalExpression("Married");
return new OrExpression(julie, married);
}
}
在這個例子中,我們定義了兩個規則,"Robert和John是男性"和"Julie是一個已婚的女性"。我們然後創建了兩個表達式對象,分別表示這兩個規則,並使用這兩個對象來解析輸入。
執行流程如下:
- 創建終結符表達式對象和非終結符表達式對象,用於表示規則。
- 調用表達式對象的
Interpret
方法,解析輸入的字元串。 - 輸出解析結果。
3. 迭代器模式(Iterator)
迭代器模式(Iterator Pattern)是一種行為型設計模式,它提供了一種方法來訪問一個對象的元素,而不需要暴露該對象的內部表示。以下是在C#中實現迭代器模式的一個簡單示例:
// 抽象聚合類
public interface IAggregate
{
IIterator CreateIterator();
void Add(string item);
int Count { get; }
string this[int index] { get; set; }
}
// 具體聚合類
public class ConcreteAggregate : IAggregate
{
private List<string> items = new List<string>();
public IIterator CreateIterator()
{
return new ConcreteIterator(this);
}
public int Count
{
get { return items.Count; }
}
public string this[int index]
{
get { return items[index]; }
set { items.Insert(index, value); }
}
public void Add(string item)
{
items.Add(item);
}
}
// 抽象迭代器
public interface IIterator
{
string First();
string Next();
bool IsDone { get; }
string CurrentItem { get; }
}
// 具體迭代器
public class ConcreteIterator : IIterator
{
private ConcreteAggregate aggregate;
private int current = 0;
public ConcreteIterator(ConcreteAggregate aggregate)
{
this.aggregate = aggregate;
}
public string First()
{
return aggregate[0];
}
public string Next()
{
string ret = null;
if (current < aggregate.Count - 1)
{
ret = aggregate[++current];
}
return ret;
}
public string CurrentItem
{
get { return aggregate[current]; }
}
public bool IsDone
{
get { return current >= aggregate.Count; }
}
}
在這個代碼中,IAggregate
是抽象聚合類,定義了CreateIterator
等方法,ConcreteAggregate
是具體聚合類,實現了IAggregate
介面。IIterator
是抽象迭代器,定義了First
、Next
等方法,ConcreteIterator
是具體迭代器,實現了IIterator
介面。
以下是一個使用這個模式的示例:
class Program
{
static void Main(string[] args)
{
IAggregate aggregate = new ConcreteAggregate();
aggregate.Add("Item A");
aggregate.Add("Item B");
aggregate.Add("Item C");
aggregate.Add("Item D");
IIterator iterator = aggregate.CreateIterator();
Console.WriteLine("Iterating over collection:");
string item = iterator.First();
while (item != null)
{
Console.WriteLine(item);
item = iterator.Next();
}
Console.ReadLine();
}
}
在這個例子中,我們創建了一個ConcreteAggregate
對象,並添加了幾個元素。然後我們通過CreateIterator
方法創建了一個迭代器,並使用這個迭代器遍歷了集合中的所有元素。
執行流程如下:
- 創建一個聚合對象,並添加一些元素。
- 通過聚合對象的
CreateIterator
方法創建一個迭代器。 - 通過迭代器的
First
方法獲取第一個元素,然後通過Next
方法獲取後續的元素,直到獲取不到元素為止。
4. 中介者模式(Mediator)
中介者模式是一種行為設計模式,它讓你能減少一組對象之間複雜的通信。它提供了一個中介者對象,此對象負責在組中的對象之間進行通信,而不是這些對象直接進行通信。
首先,讓我們定義一個中介者介面和一個具體的中介者:
// Mediator 介面聲明瞭與組件交互的方法。
public interface IMediator
{
void Notify(object sender, string ev);
}
// 具體 Mediators 實現協作行為,它負責協調多個組件。
public class ConcreteMediator : IMediator
{
private Component1 _component1;
private Component2 _component2;
public ConcreteMediator(Component1 component1, Component2 component2)
{
_component1 = component1;
_component1.SetMediator(this);
_component2 = component2;
_component2.SetMediator(this);
}
public void Notify(object sender, string ev)
{
if (ev == "A")
{
Console.WriteLine("Mediator reacts on A and triggers following operations:");
this._component2.DoC();
}
if (ev == "D")
{
Console.WriteLine("Mediator reacts on D and triggers following operations:");
this._component1.DoB();
this._component2.DoC();
}
}
}
接著,我們定義一個基礎組件類和兩個具體組件:
public abstract class BaseComponent
{
protected IMediator _mediator;
public BaseComponent(IMediator mediator = null)
{
_mediator = mediator;
}
public void SetMediator(IMediator mediator)
{
this._mediator = mediator;
}
}
// 具體 Components 實現各種功能。它們不依賴於其他組件。
// 它們也不依賴於任何具體 Mediator 類。
public class Component1 : BaseComponent
{
public void DoA()
{
Console.WriteLine("Component 1 does A.");
this._mediator.Notify(this, "A");
}
public void DoB()
{
Console.WriteLine("Component 1 does B.");
this._mediator.Notify(this, "B");
}
}
public class Component2 : BaseComponent
{
public void DoC()
{
Console.WriteLine("Component 2 does C.");
this._mediator.Notify(this, "C");
}
public void DoD()
{
Console.WriteLine("Component 2 does D.");
this._mediator.Notify(this, "D");
}
}
最後,我們來創建一個客戶端代碼:
class Program
{
static void Main(string[] args)
{
// The client code.
Component1 component1 = new Component1();
Component2 component2 = new Component2();
new ConcreteMediator(component1, component2);
Console.WriteLine("Client triggers operation A.");
component1.DoA();
Console.WriteLine();
Console.WriteLine("Client triggers operation D.");
component2.DoD();
}
}
這個示例中的各個組件通過中介者來進行通信,而不是直接通信,這樣就可以減少組件之間的依賴性,使得它們可以更容易地被獨立修改。當一個組件發生某個事件(例如"Component 1 does A")時,它會通過中介者來通知其他組件,這樣其他組件就可以根據這個事件來做出響應(例如"Component 2 does C")。
5. 備忘錄模式(Memento)
備忘錄模式是一種行為設計模式,它能保存對象的狀態,以便在後面可以恢復它。在大多數情況下,這種模式可以讓你在不破壞對象封裝的前提下,保存和恢復對象的歷史狀態。
以下是一個簡單的備忘錄模式的實現,其中有三個主要的類:Originator
(保存了一個重要的狀態,這個狀態可能會隨著時間改變),Memento
(保存了Originator
的一個快照,這個快照包含了Originator
的狀態),以及Caretaker
(負責保存Memento
)。
// Originator 類可以生成一個備忘錄,並且可以通過備忘錄恢復其狀態。
public class Originator
{
private string _state;
public Originator(string state)
{
this._state = state;
Console.WriteLine($"Originator: My initial state is: {_state}");
}
public void DoSomething()
{
Console.WriteLine("Originator: I'm doing something important.");
_state = GenerateRandomString(30);
Console.WriteLine($"Originator: and my state has changed to: {_state}");
}
private string GenerateRandomString(int length = 10)
{
string allowedSymbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
string result = string.Empty;
while (length > 0)
{
result += allowedSymbols[new Random().Next(0, allowedSymbols.Length)];
length--;
}
return result;
}
public IMemento Save()
{
return new ConcreteMemento(_state);
}
public void Restore(IMemento memento)
{
_state = memento.GetState();
Console.WriteLine($"Originator: My state has changed to: {_state}");
}
}
// 備忘錄介面提供了獲取備忘錄和原發器狀態的方法。但在該介面中並未聲明所有的方法,一些方法只在原發器中聲明。
public interface IMemento
{
string GetName();
string GetState();
DateTime GetDate();
}
// Concrete Memento 存儲原發器狀態,並通過原發器實現備份。備忘錄是不可變的,因此,沒有 set 方法。
public class ConcreteMemento : IMemento
{
private string _state;
private DateTime _date;
public ConcreteMemento(string state)
{
_state = state;
_date = DateTime.Now;
}
public string GetState()
{
return _state;
}
public string GetName()
{
return $"{_date} / ({_state.Substring(0, 9)})...";
}
public DateTime GetDate()
{
return _date;
}
}
// Caretaker 不依賴於具體備忘錄類。結果,它不會有任何訪問原發器狀態的權利,它只能獲取備忘錄的元數據。
public class Caretaker
{
private List<IMemento> _mementos = new List<IMemento>();
private Originator _originator = null;
public Caretaker(Originator originator)
{
this._originator = originator;
}
public void Backup()
{
Console.WriteLine("\nCaretaker: Saving Originator's state...");
_mementos.Add(_originator.Save());
}
public void Undo()
{
if (_mementos.Count == 0)
{
return;
}
var memento = _mementos.Last();
_mementos.Remove(memento);
Console.WriteLine("Caretaker: Restoring state to: " + memento.GetName());
try
{
_originator.Restore(memento);
}
catch (Exception)
{
Undo();
}
}
public void ShowHistory()
{
Console.WriteLine("Caretaker: Here's the list of mementos:");
foreach (var memento in _mementos)
{
Console.WriteLine(memento.GetName());
}
}
}
// 客戶端代碼
class Program
{
static void Main(string[] args)
{
Originator originator = new Originator("Super-duper-super-puper-super.");
Caretaker caretaker = new Caretaker(originator);
caretaker.Backup();
originator.DoSomething();
caretaker.Backup();
originator.DoSomething();
caretaker.Backup();
originator.DoSomething();
Console.WriteLine();
caretaker.ShowHistory();
Console.WriteLine("\nClient: Now, let's rollback!\n");
caretaker.Undo();
Console.WriteLine("\nClient: Once more!\n");
caretaker.Undo();
}
}
以上的代碼中,Originator 持有一些重要的狀態,並且提供了方法去保存它的狀態到一個備忘錄對象以及從備忘錄對象中恢復它的狀態。Caretaker 負責保存備忘錄,但是它不能操作備忘錄對象中的狀態。當用戶執行操作時,我們先保存當前的狀態,然後執行操作。如果用戶後來不滿意新的狀態,他們可以方便地從舊的備忘錄中恢復狀態。
6. 觀察者模式(Observer)
觀察者模式(Observer Pattern)是一種行為型設計模式,當一個對象的狀態發生變化時,依賴它的所有對象都會得到通知並被自動更新。以下是在C#中實現觀察者模式的一個簡單示例:
// 抽象觀察者
public interface IObserver
{
void Update();
}
// 具體觀察者
public class ConcreteObserver : IObserver
{
private string name;
public ConcreteObserver(string name)
{
this.name = name;
}
public void Update()
{
Console.WriteLine($"{name} received an update!");
}
}
// 抽象主題
public interface ISubject
{
void RegisterObserver(IObserver observer);
void RemoveObserver(IObserver observer);
void NotifyObservers();
}
// 具體主題
public class ConcreteSubject : ISubject
{
private List<IObserver> observers = new List<IObserver>();
public void RegisterObserver(IObserver observer)
{
observers.Add(observer);
}
public void RemoveObserver(IObserver observer)
{
if (observers.Contains(observer))
{
observers.Remove(observer);
}
}
public void NotifyObservers()
{
foreach (var observer in observers)
{
observer.Update();
}
}
public void ChangeState()
{
// 觸髮狀態變化,通知所有觀察者
NotifyObservers();
}
}
在這個代碼中,IObserver
是抽象觀察者,定義了Update
方法,ConcreteObserver
是具體觀察者,實現了IObserver
介面。ISubject
是抽象主題,定義了RegisterObserver
、RemoveObserver
和NotifyObservers
方法,ConcreteSubject
是具體主題,實現了ISubject
介面。
以下是一個使用這個模式的示例:
class Program
{
static void Main(string[] args)
{
ConcreteSubject subject = new ConcreteSubject();
subject.RegisterObserver(new ConcreteObserver("Observer 1"));
subject.RegisterObserver(new ConcreteObserver("Observer 2"));
subject.RegisterObserver(new ConcreteObserver("Observer 3"));
subject.ChangeState();
Console.ReadLine();
}
}
在這個例子中,我們創建了一個ConcreteSubject
對象,並註冊了三個觀察者。然後我們通過ChangeState
方法改變了主題的狀態,這會觸發主題通知所有觀察者。
執行流程如下:
- 創建一個具體主題對象。
- 創建幾個具體觀察者對象,並通過主題的
RegisterObserver
方法將這些觀察者註冊到主題中。 - 通過主題的
ChangeState
方法改變主題的狀態,這會觸發主題通知所有觀察者。
7. 狀態模式(State)
狀態模式在面向對象編程中,是一種允許對象在其內部狀態改變時改變其行為的設計模式。這種類型的設計模式屬於行為型模式。在狀態模式中,我們創建對象表示各種狀態,以及一個行為隨狀態改變而改變的上下文對象。
以下是一個狀態模式的示例。這個示例中,我們將創建一個銀行賬戶,它有兩個狀態:正常狀態(NormalState)和透支狀態(OverdrawnState)。當用戶執行操作(存款和取款)時,賬戶狀態將相應地進行更改。
首先,我們定義一個表示狀態的介面:
public interface IAccountState
{
void Deposit(Action addToBalance);
void Withdraw(Action subtractFromBalance);
void ComputeInterest();
}
然後,我們創建兩個表示具體狀態的類:
public class NormalState : IAccountState
{
public void Deposit(Action addToBalance)
{
addToBalance();
Console.WriteLine("Deposit in NormalState");
}
public void Withdraw(Action subtractFromBalance)
{
subtractFromBalance();
Console.WriteLine("Withdraw in NormalState");
}
public void ComputeInterest()
{
Console.WriteLine("Interest computed in NormalState");
}
}
public class OverdrawnState : IAccountState
{
public void Deposit(Action addToBalance)
{
addToBalance();
Console.WriteLine("Deposit in OverdrawnState");
}
public void Withdraw(Action subtractFromBalance)
{
Console.WriteLine("No withdraw in OverdrawnState");
}
public void ComputeInterest()
{
Console.WriteLine("Interest and fees computed in OverdrawnState");
}
}
然後,我們創建一個Context類,它使用這些狀態來執行其任務:
public class BankAccount
{
private IAccountState _state;
private double _balance;
public BankAccount(IAccountState state)
{
_state = state;
_balance = 0;
}
public void Deposit(double amount)
{
_state.Deposit(() => _balance += amount);
StateChangeCheck();
}
public void Withdraw(double amount)
{
_state.Withdraw(() => _balance -= amount);
StateChangeCheck();
}
public void ComputeInterest()
{
_state.ComputeInterest();
}
private void StateChangeCheck()
{
if (_balance < 0.0)
_state = new OverdrawnState();
else
_state = new NormalState();
}
}
現在,你可以創建一個實例並運行一個Demo來測試這個狀態模式的代碼:
public class Program
{
public static void Main(string[] args)
{
var account = new BankAccount(new NormalState());
account.Deposit(1000); // Deposit in NormalState
account.Withdraw(2000); // Withdraw in NormalState; No withdraw in OverdrawnState
account.Deposit(100); // Deposit in OverdrawnState
account.ComputeInterest(); // Interest and fees computed in OverdrawnState
Console.ReadKey();
}
}
這個程式首先在正常狀態下進行存款操作,然後嘗試進行取款操作。由於取款金額超過賬戶餘額,所以賬戶進入透支狀態,並阻止進一步的取款操作。但存款仍然被允許,以使賬戶回歸到正常狀態。計算利息的行為也根據賬戶的狀態變化而變化。
8. 策略模式(Strategy)
策略模式定義了一系列的演算法,並將每一個演算法封裝起來,使得它們可以相互替換。策略模式讓演算法獨立於使用它的客戶而獨立變化。
以下是一個簡單的策略模式的C#實現。這個例子中,我們將創建一個排序策略,比如快速排序和冒泡排序,它們實現同一個介面,然後創建一個Context類,它使用這些策略來執行排序操作。
首先,我們定義一個表示排序策略的介面:
public interface ISortStrategy
{
void Sort(List<int> list);
}
然後,我們創建兩個表示具體策略的類:
public class QuickSort : ISortStrategy
{
public void Sort(List<int> list)
{
list.Sort(); // Quick sort is in-place but here we are using built-in method
Console.WriteLine("QuickSorted list ");
}
}
public class BubbleSort : ISortStrategy
{
public void Sort(List<int> list)
{
int n = list.Count;
for (int i = 0; i < n - 1; i++)
for (int j = 0; j < n - i - 1; j++)
if (list[j] > list[j + 1])
{
// swap temp and list[i]
int temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
}
Console.WriteLine("BubbleSorted list ");
}
}
然後,我們創建一個Context類,它使用這些策略來執行其任務:
public class SortedList
{
private List<int> _list = new List<int>();
private ISortStrategy _sortstrategy;
public void SetSortStrategy(ISortStrategy sortstrategy)
{
this._sortstrategy = sortstrategy;
}
public void Add(int num)
{
_list.Add(num);
}
public void Sort()
{
_sortstrategy.Sort(_list);
// Print sorted list
foreach (int num in _list)
{
Console.Write(num + " ");
}
Console.WriteLine();
}
}
現在,你可以創建一個實例並運行一個Demo來測試這個策略模式的代碼:
public class Program
{
public static void Main(string[] args)
{
SortedList sortedList = new SortedList();
sortedList.Add(1);
sortedList.Add(5);
sortedList.Add(3);
sortedList.Add(4);
sortedList.Add(2);
sortedList.SetSortStrategy(new QuickSort());
sortedList.Sort(); // Output: QuickSorted list 1 2 3 4 5
sortedList.SetSortStrategy(new BubbleSort());
sortedList.Sort(); // Output: BubbleSorted list 1 2 3 4 5
Console.ReadKey();
}
}
這個程式首先創建了一個未排序的列表,然後它首先使用快速排序策略進行排序,接著又使用冒泡排序策略進行排序。
9. 模板方法模式(Template Method)
模板方法模式定義了一個操作中演算法的骨架,將這些步驟延遲到子類中。模板方法使得子類可以不改變演算法的結構即可重定義該演算法的某些特定步驟。
以下是一個模板方法模式的示例。這個示例中,我們將創建一個烹飪食物的過程,這個過程有一些固定的步驟(例如準備材料,清理),但是具體的烹飪步驟則取決於具體的食物。
首先,我們定義一個抽象的模板類:
public abstract class CookingProcedure
{
// The 'Template method'
public void PrepareDish()
{
PrepareIngredients();
Cook();
CleanUp();
}
public void PrepareIngredients()
{
Console.WriteLine("Preparing the ingredients...");
}
// These methods will be overridden by subclasses
public abstract void Cook();
public void CleanUp()
{
Console.WriteLine("Cleaning up...");
}
}
然後,我們創建兩個具體的子類,它們分別實現了具體的烹飪步驟:
public class CookPasta : CookingProcedure
{
public override void Cook()
{
Console.WriteLine("Cooking pasta...");
}
}
public class BakeCake : CookingProcedure
{
public override void Cook()
{
Console.WriteLine("Baking cake...");
}
}
現在,你可以創建一個實例並運行一個Demo來測試這個模板方法模式的代碼:
public class Program
{
public static void Main(string[] args)
{
CookingProcedure cookingProcedure = new CookPasta();
cookingProcedure.PrepareDish();
Console.WriteLine();
cookingProcedure = new BakeCake();
cookingProcedure.PrepareDish();
Console.ReadKey();
}
}
在這個程式中,我們首先創建了一個CookPasta
對象,然後調用其PrepareDish
方法。然後,我們創建了一個BakeCake
對象,再次調用其PrepareDish
方法。這兩個對象雖然具有不同的Cook
方法,但是它們的PrepareDish
方法的結構(即演算法的骨架)是相同的。
10. 訪問者模式(Visitor)
訪問者模式(Visitor Pattern)是一種將演算法與對象結構分離的軟體設計模式。這種模式的基本想法就是通過所謂的"訪問者"來改變元素的操作。這樣一來,元素的類可以用於表示元素結構,而具體的操作則可以在訪問者類中定義。
以下是一個使用C#實現的訪問者模式示例,包括了詳細的註釋和執行流程。
這個示例中有三個主要部分:訪問者(IVisitor)、可訪問元素(IElement)和元素結構(ObjectStructure)。同時有具體訪問者(ConcreteVisitor)和具體元素(ConcreteElement)。
// 訪問者介面
public interface IVisitor
{
void VisitConcreteElementA(ConcreteElementA concreteElementA);
void VisitConcreteElementB(ConcreteElementB concreteElementB);
}
// 具體訪問者A
public class ConcreteVisitorA : IVisitor
{
public void VisitConcreteElementA(ConcreteElementA concreteElementA)
{
Console.WriteLine($"{concreteElementA.GetType().Name} is being visited by {this.GetType().Name}");
}
public void VisitConcreteElementB(ConcreteElementB concreteElementB)
{
Console.WriteLine($"{concreteElementB.GetType().Name} is being visited by {this.GetType().Name}");
}
}
// 具體訪問者B
public class ConcreteVisitorB : IVisitor
{
public void VisitConcreteElementA(ConcreteElementA concreteElementA)
{
Console.WriteLine($"{concreteElementA.GetType().Name} is being visited by {this.GetType().Name}");
}
public void VisitConcreteElementB(ConcreteElementB concreteElementB)
{
Console.WriteLine($"{concreteElementB.GetType().Name} is being visited by {this.GetType().Name}");
}
}
// 元素介面
public interface IElement
{
void Accept(IVisitor visitor);
}
// 具體元素A
public class ConcreteElementA : IElement
{
public void Accept(IVisitor visitor)
{
visitor.VisitConcreteElementA(this);
}
}
// 具體元素B
public class ConcreteElementB : IElement
{
public void Accept(IVisitor visitor)
{
visitor.VisitConcreteElementB(this);
}
}
// 對象結構
public class ObjectStructure
{
private List<IElement> _elements = new List<IElement>();
public void Attach(IElement element)
{
_elements.Add(element);
}
public void Detach(IElement element)
{
_elements.Remove(element);
}
public void Accept(IVisitor visitor)
{
foreach (var element in _elements)
{
element.Accept(visitor);
}
}
}
執行流程如下:
- 創建具體元素ConcreteElementA和ConcreteElementB的實例。
- 創建對象結構ObjectStructure的實例,並將步驟1創建的具體元素添加到對象結構中。
- 創建具體訪問者ConcreteVisitorA和ConcreteVisitorB的實例。
- 調用對象結構的Accept方法,傳入步驟3創建的具體訪問者,使具體訪問者訪問對象結構中的所有元素。
以下是一個使用上述代碼的示例:
public class Program
{
public static void Main()
{
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.Attach(new ConcreteElementA());
objectStructure.Attach(new ConcreteElementB());
ConcreteVisitorA visitorA = new ConcreteVisitorA();
ConcreteVisitorB visitorB = new ConcreteVisitorB();
objectStructure.Accept(visitorA);
objectStructure.Accept(visitorB);
Console.ReadKey();
}
}
這個程式會列印出訪問者A和訪問者B分別訪問具體元素A和具體元素B的信息。
技術交流
.NET Core交流群:737776595
來自token的分享