使用c#實現23種常見的設計模式

来源:https://www.cnblogs.com/hejiale010426/archive/2023/06/05/17457761.html
-Advertisement-
Play Games

# 使用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();
    }
}

以上代碼中定義了兩個產品ProductAProductB,這兩個產品都實現了IProduct介面。接著我們有兩個Creator類,CreatorACreatorB,它們都繼承自抽象基類CreatorCreatorA工廠創建ProductACreatorB工廠創建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();
    }
}

當你運行這個程式時,它會顯示出ProductAProductBOperation方法返回的結果。這說明我們已經成功地使用工廠方法模式創建了產品實例。每個工廠類決定了它創建哪個產品的實例。這種方式使得客戶端代碼不需要直接實例化產品類,而只需要依賴工廠介面,增加了程式的靈活性。

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();
    }
}

以上代碼定義了兩種動物DogCat,它們都實現了IAnimal介面。然後我們有兩個工廠類,DogFactoryCatFactory,它們都繼承自IAnimalFactoryDogFactory生產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對象。當我們運行這個程式時,會看到原始對象和克隆對象的屬性是相同的,這表明我們已經成功地克隆了一個對象。

執行流程如下:

  1. 創建一個具體的原型對象,為其屬性賦值。
  2. 調用原型對象的Clone方法,創建一個新的對象,該對象的屬性與原型對象的屬性相同。
  3. 列印原型對象和克隆對象的屬性,驗證它們是否相同。

結構型模式: 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是擴充的抽象類,它繼承自AbstractionConcreteImplementorAConcreteImplementorB是實現類,它們實現了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方法。

執行流程如下:

  1. 創建實現類的實例。
  2. 創建抽象類的實例,抽象類的實例有一個實現類的實例。
  3. 調用抽象類的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();
    }
}

在這個例子中,我們創建了一個根節點,併在其中添加了兩個葉子節點。然後我們創建了一個複合節點,併在其中添加了兩個葉子節點,然後我們把複合節點添加到根節點中。我們還在複合節點中添加了另一個複合節點。最後,我們又在根節點中添加和刪除了一個葉子節點,然後顯示了樹的結構。

執行流程如下:

  1. 創建組合和葉子對象。
  2. 通過調用組合對象的Add方法將葉子對象和其他組合對象添加到組合對象中。
  3. 通過調用組合對象的Remove方法將葉子對象從組合對象中移除。
  4. 調用組合對象的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是具體組件,它實現了ComponentOperation方法。Decorator是一個抽象裝飾器,它包含一個Component對象,並重寫了Operation方法。ConcreteDecoratorAConcreteDecoratorB是具體的裝飾器,它們繼承了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方法。這樣,我們就可以在運行時動態地添加功能。

執行流程如下:

  1. 創建一個具體組件對象並調用其操作。
  2. 創建一個裝飾器對象,該對象裝飾了具體組件,並調用其操作。在操作中,裝飾器首先調用具體組件的操作,然後執行額外的操作。
  3. 創建另一個裝飾器對象,裝飾前一個裝飾器,並調用其操作。在操作中,這個裝飾器首先調用前一個裝飾器的操作,然後執行額外的操作。

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;
    }
}

在這個代碼中,SubSystemASubSystemBSubSystemC都是子系統,每個子系統都有一個操作。Facade是一個外觀類,它封裝了對子系統的操作,提供了一個統一的介面。

以下是一個使用這個模式的示例:

class Program
{
    static void Main(string[] args)
    {
        Facade facade = new Facade();
        Console.WriteLine(facade.OperationWrapper());

        Console.ReadLine();
    }
}

在這個例子中,我們創建了一個Facade對象,並調用了它的OperationWrapper方法。這個方法封裝了對子系統的操作,使得客戶端可以不直接操作子系統,而是通過外觀類操作子系統。

執行流程如下:

  1. 創建一個外觀對象。

  2. 通過調用外觀對象的方法,間接地操作子系統。

  3. 子系統的操作被封裝在外觀對象的方法中,客戶端不需要直接操作子系統。

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對象,並通過它創建了兩個享元對象。註意,當我們試圖創建第三個享元對象時,工廠實際上返回了第一個享元對象的引用,因為這兩個對象的內在狀態是相同的。

執行流程如下:

  1. 創建一個享元工廠對象。
  2. 通過享元工廠獲取享元對象。如果對象已經存在,則返回現有對象;否則,創建新對象。
  3. 執行享元對象的操作。
  4. 顯示當前享元對象的數量。

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();
    }
}

在這個例子中,我們首先直接調用了RealSubjectRequest方法,然後我們通過代理調用了相同的方法。註意,在通過代理調用Request方法時,代理還執行了其他的操作,如檢查訪問許可權和記錄日誌。

執行流程如下:

  1. 創建一個真實主題對象,並直接調用其Request方法。
  2. 創建一個代理對象,代理對象包含一個真實主題的引用。
  3. 通過代理對象調用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對象。然後我們通過InvokerSetCommand方法設置了命令,並通過ExecuteCommand方法執行了命令。

執行流程如下:

  1. 創建一個接收者對象。
  2. 創建一個具體命令對象,並將接收者對象傳遞給它。
  3. 創建一個調用者或發送者對象。
  4. 通過調用者對象的SetCommand方法設置命令。
  5. 通過調用者對象的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是一個已婚的女性"。我們然後創建了兩個表達式對象,分別表示這兩個規則,並使用這兩個對象來解析輸入。

執行流程如下:

  1. 創建終結符表達式對象和非終結符表達式對象,用於表示規則。
  2. 調用表達式對象的Interpret方法,解析輸入的字元串。
  3. 輸出解析結果。

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是抽象迭代器,定義了FirstNext等方法,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方法創建了一個迭代器,並使用這個迭代器遍歷了集合中的所有元素。

執行流程如下:

  1. 創建一個聚合對象,並添加一些元素。
  2. 通過聚合對象的CreateIterator方法創建一個迭代器。
  3. 通過迭代器的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是抽象主題,定義了RegisterObserverRemoveObserverNotifyObservers方法,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方法改變了主題的狀態,這會觸發主題通知所有觀察者。

執行流程如下:

  1. 創建一個具體主題對象。
  2. 創建幾個具體觀察者對象,並通過主題的RegisterObserver方法將這些觀察者註冊到主題中。
  3. 通過主題的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);
        }
    }
}

執行流程如下:

  1. 創建具體元素ConcreteElementA和ConcreteElementB的實例。
  2. 創建對象結構ObjectStructure的實例,並將步驟1創建的具體元素添加到對象結構中。
  3. 創建具體訪問者ConcreteVisitorA和ConcreteVisitorB的實例。
  4. 調用對象結構的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的分享


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在B站有許多坤坤的視頻,作為一名ikun,讓我們寫個爬蟲研究一下視頻的視頻的名字、鏈接、觀看次數、彈幕、發佈時間以及作者。我們用selenium來實現這個爬蟲,由於要獲取的數據比較多,我們寫幾個函數來實現這個爬蟲。 先倒入需要用到的庫,包括selenium, time ,BeautifulSoup ...
  • 鑒於公司內網安裝的python版本為python3.6.5,而此時又需要安裝第三方庫pytest,本來是想直接在Python官網PyPI直接搜對應可匹配跑python3.6.5版本的pytest進行下載然後傳到內網安裝即可,但是發現pytest依賴別的第三方庫,根據報錯裝了幾個依賴的第三方庫之後,發 ...
  • 基於java的座位預約系統,可以用於圖書館占位系統,圖書館座位預約系統,大學自習室占座系統,自習室座位預約系統,圖書館預約占座系統,自習室預約占座系統,座位預約系統等等; ...
  • 清醒點[toc] # Java虛擬線程 > 翻譯自 screencapture-pradeesh-kumar-medium-an-era-of-virtual-threads-java ```mermaid flowchart LR introduction-->a(why thread)-->b( ...
  • 基於java的倉庫管理系統設計與實現,可適用於出庫、入庫、庫存管理,基於java的出入庫管理,java出入庫管理系統,基於java的WMS倉庫管理系統,庫存物品管理系統。 ...
  • # 1、背景 在我們開發的過程中有這麼一種場景, `/projectA` 目錄是 `hadoopdeploy`用戶創建的,他對這個目錄有`wrx`許可權,同時這個目錄屬於`supergroup`,在這個組中的用戶也具有這個目錄的`wrx`許可權,對於其他人,不可訪問這個目錄。現在有這麼一個特殊的用戶`r ...
  • 有時候,我們為了方便,我們往往使用擴展函數的代碼方式創建很多GridView的操作功能,如在隨筆《在DevExpress中使用BandedGridView表格實現多行表頭的處理》中介紹過多行表頭的創建及綁定處理,在《基於DevExpress的GridControl實現的一些界面處理功能》也介紹了一些... ...
  • ## 一:背景 ### 1. 講故事 在這麼多的案例分析中,往往會發現一些案例是卡死線上程的內核態棧上,但拿過來的dump都是用戶態模式下,所以無法看到內核態棧,這就比較麻煩,需要讓朋友通過其他方式生成一個藍屏的dump,這裡我們簡單彙總下。 ## 二:如何生成內核態dump ### 1. 案例代碼 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...