C# 設計模式·行為型模式

来源:http://www.cnblogs.com/onegarden/archive/2017/07/18/7201907.html
-Advertisement-
Play Games

這裡列舉行為型模式·到此23種就列完了···這裡是看著菜鳥教程來實現··,他裡邊列了25種,其中過濾器模式和空對象模式應該不屬於所謂的23種模式責任鏈模式:為請求創建一個接收者對象的鏈,對請求的發送者和接收者進行解耦,大部分用於web中吧。。Task中的continuewith和微軟的tpl數據流應 ...



這裡列舉行為型模式·到此23種就列完了···這裡是看著菜鳥教程來實現··,他裡邊列了25種,其中過濾器模式和空對象模式應該不屬於所謂的23種模式
責任鏈模式:為請求創建一個接收者對象的鏈,對請求的發送者和接收者進行解耦,大部分用於web中吧。。
Task中的continuewith和微軟的tpl數據流應該是類似這種模式的實現吧

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//責任鏈模式
namespace ExercisePrj.Dsignmode
{
    public abstract class AbstractLogger
    {
        public static int INFO = 1;
        public static int DEBUG = 2;
        public static int ERROR = 3;
        protected int level;
        //責任鏈中的下一個對象
        protected AbstractLogger nextLogger;
        public void SetNextLogger(AbstractLogger next)
        {
            nextLogger = next;
        }
        public void LogMessage(int level,string message)
        {
            if(this.level<=level)
            {
                Write(message);
            }
            if(nextLogger!=null)
            {
                nextLogger.LogMessage(level, message);
            }
        }
        protected abstract void Write(string message);
    }
    public class ConsoleLogger : AbstractLogger
    {

       public ConsoleLogger(int level)
        {
            this.level = level;
        }

       protected  override void Write(string message)
        {
            Console.WriteLine("Standard Console::Logger: " + message);
        }
    }
    public class ErrorLogger : AbstractLogger
    {

       public ErrorLogger(int level)
        {
            this.level = level;
        }

       protected override void Write(String message)
        {
            Console.WriteLine("Error Console::Logger: " + message);
        }
    }
    public class FileLogger : AbstractLogger
    {
       public FileLogger(int level)
        {
            this.level = level;
        }

       protected override void Write(String message)
        {
            Console.WriteLine("File::Logger: " + message);
        }
    }
}

命令模式(Command Pattern):請求以命令的形式執行,CAD的的命令應該就是以這種方式執行的·二次開發的時候通過特性標識和繼承他的介面來添加命令,非常方便

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//命令模式
namespace ExercisePrj.Dsignmode
{
    public interface IOrder
    {
        void Execute();
    }
    public class Stock
    {
        private string name = "ABC";
        private int quantity = 10;

        public void Buy()
        {
            Console.WriteLine("Stock name:{0},quantity:{1},bought",name,quantity);
        }
        public void Sell()
        {
            Console.WriteLine("Stock name:{0},quantity:{1}sold", name, quantity);
        }
    }
    //請求類
    public class BuyStock : IOrder
    {
       private Stock abcStock;

        public BuyStock(Stock abcStock)
        {
            this.abcStock = abcStock;
        }

        public void Execute()
        {
            abcStock.Buy();
        }
    }
    //繼承介面的實體
    public class SellStock : IOrder
    {
       private Stock abcStock;

        public SellStock(Stock abcStock)
        {
            this.abcStock = abcStock;
        }

        public void Execute()
        {
            abcStock.Sell();
        }
    }

    //命令調用類
    public class Broker
    {
        private List<IOrder> orderList = new List<IOrder>();

        public void takeOrder(IOrder order)
        {
            orderList.Add(order);
        }

        public void placeOrders()
        {
            foreach (IOrder order in orderList)
            {
                order.Execute();
            }
            orderList.Clear();
        }
    }

}

解釋器模式:就是實現一種表達式介面,C#的各種表達式就是這種實現吧··這玩意跟富文本編輯器一樣是個大坑吧··,做好了確實很好使,一不小心就得跪

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//解釋器模式
namespace ExercisePrj.Dsignmode
{
    public interface Expression
    {
         bool Interpret(string context);
    }
    public class TerminalExpression : Expression
    {
       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 : Expression
    {
        private Expression expr1 = null;
        private Expression expr2 = null;
        public OrExpression(Expression expr1, Expression expr2)
        {
            this.expr1 = expr1;
            this.expr2 = expr2;
        }
        public bool Interpret(String context)
        {
            return expr1.Interpret(context) || expr2.Interpret(context);
        }
    }
    public class AndExpression : Expression
    {
        private Expression expr1 = null;
        private Expression expr2 = null;

        public AndExpression(Expression expr1, Expression expr2)
        {
            this.expr1 = expr1;
            this.expr2 = expr2;
        }
        public bool Interpret(String context)
        {
            return expr1.Interpret(context) && expr2.Interpret(context);
        }
        }
}


迭代器模式(Iterator Pattern):.NET自帶介面···,直接實現就行了··註意又泛型介面和非泛型介面··非泛型介面迭代對象返回的是object,泛型介面返回的直接就是對象了,還有通過yield的簡化寫法不用額外去實現IEnumerator介面

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExercisePrj.Dsignmode
{
    public class IteratorEx : IEnumerable //<IteratorEx>
    {
        public string Name;
        private List<IteratorEx> list = new List<IteratorEx>();

        //public IEnumerator<IteratorEx> GetEnumerator()
        //{
        //    foreach (var l in list)
        //    {
        //        yield return l;
        //    }
        //}

        public void SetList(List<IteratorEx> data)
        {
            list = data;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            foreach (var l in list)
            {
                yield return l;
            }
            //return new IteratorExEnum(list.ToArray());
        }
    }
    public class IteratorExEnum : IEnumerator
    {
        private IteratorEx[] list;
        private int position = -1;
        public IteratorExEnum(IteratorEx[] data)
        {
            list = data;
        }
        public object Current
        {
            get
            {
                try
                {
                    return list[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }

        public bool MoveNext()
        {
            position++;
            return position < list.Length;
        }

        public void Reset()
        {
            position = -1;
        }
    }

}

 
中介者模式(Mediator Pattern):用一個中介對象封裝一些對象的交互,中介者使對象不用顯式的互相引用,MVC和mvp 的c和p都是類似這玩意的實現吧

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExercisePrj.Dsignmode
{
    //中介類
    public class ChatRoom
    {
        public static void ShowMessage(User user, string msg)
        {
            Console.WriteLine(new DateTime().ToString()+"["+ user.Name + "] : " + msg);
        }
    }
    public class User
    {
        public string Name { get; set; }

        public User(string name)
        {
            Name = name;
        }

        public void SendMessage(String message)
        {
            ChatRoom.ShowMessage(this, message);
        }
    }


}

備忘錄模式(Memento Pattern):在不破壞封裝的前提下,捕獲一個對象的內部狀態,併在對象之外保存,

大部分支持回退的操作場景下應該都是這種模式··之前做的軟體中有畫圖的操作···支持後退,實現方式非常簡單粗暴··,直接吧圖層的畫圖對象克隆一份保存··只支持5還是10步,講道理這麼實現確實有點那啥了···

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExercisePrj.Dsignmode
{
    public class Memento
    {
        public string State { get; }
        public Memento(string state)
        {
            State = state;
        }
    }
    public class Originator
    {
        public string State { get; set; }

        public Memento SaveStateToMemento()
        {
            return new Memento(State);
        }

        public void GetStateFromMemento(Memento Memento)
        {
            State = Memento.State;
        }
    }
    public class CareTaker
    {
        private List<Memento> mementoList = new List<Memento>();

        public void Add(Memento state)
        {
            mementoList.Add(state);
        }

        public Memento Get(int index)
        {
            return mementoList[index];
        }
    }

}

觀察者模式(Observer Pattern):.net自帶的有介面提供來實現觀察者模式···這裡照著msdn來實現一遍,自帶的介面裡邊還實現了資源的釋放··,之前併發編程裡邊的rx也是這個模式的具體實現·

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//觀察者模式
namespace ExercisePrj.Dsignmode
{

    public class Subject: IObservable<Subject>
    {
        public int State {get; set;}
        public Subject(int state)
        {
            State = state;
        }
        private List<IObserver<Subject>> observers = new List<IObserver<Subject>>();

        public IDisposable Subscribe(IObserver<Subject> observer)
        {
            if (!observers.Contains(observer))
                observers.Add(observer);
            return new Unsubscriber(observers, observer);
        }
        private class Unsubscriber : IDisposable
        {
            private List<IObserver<Subject>> _observers;
            private IObserver<Subject> _observer;

            public Unsubscriber(List<IObserver<Subject>> observers, IObserver<Subject> observer)
            {
                this._observers = observers;
                this._observer = observer;
            }

            public void Dispose()
            {
                if (_observer != null && _observers.Contains(_observer))
                    _observers.Remove(_observer);
            }
        }

        public void TrackLocation(Subject ob)
        {
            Console.WriteLine("start");
            foreach (var observer in observers)
            {
                if (ob==null)
                    observer.OnError(new Exception("unknowExeption"));
                else
                    observer.OnNext(ob);
            }
        }

        public void EndTransmission()
        {
            foreach (var observer in observers.ToArray())
                if (observers.Contains(observer))
                    observer.OnCompleted();

            observers.Clear();
        }

    }


    public class BinaryObserver : IObserver<Subject>
    {
        public void OnCompleted()
        {
            Console.WriteLine("complete");
        }

        public void OnError(Exception error)
        {
            Console.WriteLine(error.Message);
        }

        public void OnNext(Subject value)
        {
            Console.WriteLine("Binary String: " + Convert.ToString(value.State, 2));
        }
    }
    public class OctalObserver : IObserver<Subject>
    {
        public void OnCompleted()
        {
            Console.WriteLine("complete");
        }

        public void OnError(Exception error)
        {
            Console.WriteLine(error.Message);
        }

        public void OnNext(Subject value)
        {
            Console.WriteLine("Octal String: " + Convert.ToString(value.State, 8));
        }

    }
    public class HexaObserver : IObserver<Subject>
    {
        public void OnCompleted()
        {
            Console.WriteLine("complete");
        }

        public void OnError(Exception error)
        {
            Console.WriteLine(error.Message);
        }

        public void OnNext(Subject value)
        {
            Console.WriteLine("Hex String: " + Convert.ToString(value.State,16));
        }
    }
}


狀態模式(State Pattern):當對象內部狀態發生改變時,行為也跟著改變

這個模式是為瞭解決類裡邊的大量if和swicth語句,講道理例子寫的有點怪···主體是context

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExercisePrj.Dsignmode
{
    public class Context
    {
        public State State { get; set; }

        public Context()
        {
            State = null;
        }
    }
    public interface State
    {
         void DoAction(Context context);
    }

    public class StartState : State
    {
       public void DoAction(Context context)
        {
            Console.WriteLine("Player is in start state");
            context.State = this;
        }

        public override string ToString()
        {
            return "Start State";
        }
    }
    public class StopState : State
    {

       public void DoAction(Context context)
        {
            Console.WriteLine("Player is in stop state");
            context.State = this;
        }

        public override string  ToString()
        {
            return "Stop State";
        }
    }
}

空對象模式(Null Object Pattern):就是吧對空值的判斷定義一個啥也不做的實體對象出來··C#的Nullable就是這個的實現···這玩意不在23種設計模式裡邊···

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExercisePrj.Dsignmode
{
    public abstract class AbstractCustomer
    {
        public abstract bool IsNull();
        public abstract string Name { get; }
    }
    public class RealCustomer : AbstractCustomer
    {
        public override string Name { get; }

        public RealCustomer(string name)
        {
            Name = name;
        }
        public override bool IsNull()
        {
            return false;
        }
    }
    public class NullCustomer : AbstractCustomer
    {
            public override string Name { get { return "Not Available in Customer Database"; } }
            public override bool IsNull()
            {
                return true;
            }
    }
    public class CustomerFactory
    {
        public static  string[] names = {"Rob", "Joe", "Julie"};
         public static AbstractCustomer getCustomer(string name)
        {
            if(names.Contains(name))
            {
                return new RealCustomer(name);
            }
            return new NullCustomer();
        }
    }
}

策略模式(Strategy Pattern):定義一系列演算法,封裝成類,可以相互替換,通過構造不同的類,執行不同的操作。這樣做方便調用,添加新的演算法也方便,

最後加了自己之前對這個模式的奇葩寫法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace ExercisePrj.Dsignmode
{
    public interface IStrategy
    {
         int DoOperation(int num1, int num2);
    }
    public class OperationAdd : IStrategy
    {
        
       public int DoOperation(int num1, int num2)
        {
            return num1 + num2;
        }
    }

    public class OperationSubstract : IStrategy
    {

        public int DoOperation(int num1, int num2)
        {
            return num1 - num2;
        }
    }
    public class OperationMultiply : IStrategy
    {

        public int DoOperation(int num1, int num2)
        {
             return num1 * num2;
        }
    }

    public class ContextEx
    {
        private IStrategy strategy;

        public ContextEx(IStrategy strategy)
        {
            this.strategy = strategy;
        }

        public int ExecuteStrategy(int num1, int num2)
        {
            return strategy.DoOperation(num1, num2);
        }

        //奇葩的寫法簡單粗暴
        private Dictionary<string, Func<int, int, int>> funcs = new Dictionary<string, Func<int, int, int>>();
        public int ExecuteStrategy(string name, int num1, int num2)
        {
            if(funcs.Count==0)
            {
                //反射寫法
                var assembly = Assembly.GetExecutingAssembly();
                var types = assembly.GetTypes();
                foreach (var t in types)
                {
                    if (t.GetInterface("IStrategy") != null)
                    {
                        var instance = assembly.CreateInstance(t.FullName) as IStrategy;
                        funcs.Add(t.Name, instance.DoOperation);
                    }
                }
                //直接添加
                //funcs.Add("OperationAdd", new Func<int, int, int>((n1, n2) => { return n1 + n2; }));
                //funcs.Add("OperationSubstract", new Func<int, int, int>((n1, n2) => { return n1 - n2; }));
                //funcs.Add("OperationMultiply", new Func<int, int, int>((n1, n2) => { return n1 * n2; }));
            }
            return funcs[name](num1, num2);
        }


    }
}

模板模式(Template Pattern):.net的泛型就是這個模式的實現吧··照著模子寫就行了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExercisePrj.Dsignmode
{
    public abstract class Game
    {
       public  abstract void Initialize();
        public  abstract void StartPlay();
        public abstract void EndPlay();

        //模板
        public void play()
        {

            //初始化游戲
            Initialize();
            //開始游戲
            StartPlay();
            //結束游戲
            EndPlay();
        }
    }
    public class Cricket : Game
    {
        public override void EndPlay()
        {
            Console.WriteLine("Cricket Game Finished!");
        }

        public override void Initialize()
        {
            Console.WriteLine("Cricket Game Initialized! Start playing.");
        }


        public override void StartPlay()
        {
            Console.WriteLine("Cricket Game Started. Enjoy the game!");
        }
    }
}

訪問者模式(Visitor Pattern):在被訪問的類裡邊加一個對外提供接待訪問的介面
 吧數據結構和對應的操作分開·添加操作很容易,但是如果結構變化多的化,改起來就麻煩了··
 沒研究沒用過····

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExercisePrj.Dsignmode
{

    public interface IComputerPartVisitor
    {
        void Visit(Computer computer);
        void Visit(Mouse mouse);
        void Visit(Keyboard keyboard);
        void Visit(Monitor monitor);
    }

    public interface IComputerPart
    {
        void Accept(IComputerPartVisitor computerPartVisitor);
    }

    public class Keyboard  : IComputerPart
    {

       public void Accept(IComputerPartVisitor computerPartVisitor)
        {
            computerPartVisitor.Visit(this);
        }
    }
    public class Monitor  : IComputerPart
    {

       public void Accept(IComputerPartVisitor computerPartVisitor)
        {
            computerPartVisitor.Visit(this);
        }
}
    public class Mouse  : IComputerPart
    {
       public void Accept(IComputerPartVisitor computerPartVisitor)
        {
            computerPartVisitor.Visit(this);
        }
    }
    public class Computer : IComputerPart
    {
        IComputerPart [] parts;
        public Computer()
        {
            parts = new IComputerPart[] { new Mouse(), new Keyboard(), new Monitor() };
        }
        public void Accept(IComputerPartVisitor computerPartVisitor)
        {
            for (int i = 0; i < parts.Length; i++)
            {
                parts[i].Accept(computerPartVisitor);
            }
            computerPartVisitor.Visit(this);
        }
    }

    public class ComputerPartDisplayVisitor : IComputerPartVisitor
    {
        public void Visit(Computer computer)
        {
            Console.WriteLine("Displaying Computer.");
        }
        public void Visit(Mouse mouse)
        {
            Console.WriteLine("Displaying Mouse.");
        }
        public void Visit(Keyboard keyboard)
        {
            Console.WriteLine("Displaying Keyboard.");
        }
        public void Visit(Monitor monitor)
        {
            Console.WriteLine("Displaying Monitor.");
        }
    }
}

 


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

-Advertisement-
Play Games
更多相關文章
  • python 第二例,爬取百度貼吧的帖子,獲取帖子的標題,內容,所在樓層,發佈時間 其中存在一個問題,當該帖子是手機端發佈的帖子,此時在頁面中會有標識,因此多一個span標簽,與樓層和發佈時間的標簽一樣 解決方法: 目潛想到的解決方法是通過判斷爬到的值來進行選擇,但解決方案效率肯定低,因此未使用,等 ...
  • 1.__doc__ 表示類的描述信息 2.__module__ 和 __class__ __module__ 表示當前操作對象在哪個模塊 __class__ 表示當前操作對象的類是什麼 3. __init__ 構造方法 通過類創建對象時,自動觸發執行 4. __del__ 析構方法 當對象在記憶體中被 ...
  • 題目描述 Each of Farmer John's N (4 <= N <= 16) cows has a unique serial number S_i (1 <= S_i <= 25,000). The cows are so proud of it that each one now we ...
  • 這是第一次開始寫博客,也不知道怎麼寫,就是自己的學習的一些東西。 今天碰到的問題是怎麼用IDEA軟體把Java文件導出為一個可以運行的jar文件,然後轉成可運行的exe文件。 以一個小游戲的文件為例: Artifacts Config File -> Project Structure -> Art ...
  • 1,try…except (1) 關註是否會引起異常的語句放在try段; (2) 根據異常的不同,except可以有多個分支; (3) 可以有一個else分支,表示沒有異常發生。 例如: 2,raise (1) 假如在try部分有條件分支,而分支里可能出現異常,可以用raise來提取異常; (2) ... ...
  • 描述:新bean和舊bean擁有相同的欄位屬性。將舊bean的屬性值,賦給新bean。 Java代碼如下: 該方法會拋異常,要註意檢查get方法的寫法,和新舊bean欄位是否一致。 ...
  • 演算法:當數據量很大適宜採用該方法。採用二分法查找時,數據需是有序不重覆的。 基本思想:假設數據是按升序排序的,對於給定值 x,從序列的中間位置開始比較,如果當前位置值等於 x,則查找成功;若 x 小於當前位置值,則在數列的前半段中查找;若 x 大於當前位置值則在數列的後半段中繼續查找,直到找到為止。 ...
  • urllib.parse.urlencode()和urllib.parse.unquote() 編碼工作使用urllib.parse的urlencode()函數,幫我們將key:value這樣的鍵值對轉換成"key=value"這樣的字元串,解碼工作可以使用urllib的unquote()函數。 一 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...