1. 程式人生 > >設計模式(c#)程式碼總結

設計模式(c#)程式碼總結

設計模式分為三種類型

  • 建立型模式:簡單工廠、工廠方法模式、抽象工廠模式、建造者模式、原型模式、單例模式

  • 結構型模式:介面卡模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。

  • 行為型模式:模版方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、直譯器模式、狀態模式、策略模式、職責鏈模式、訪問者模式。


建立型模式

一、簡單工廠模式

模式說明

簡單工廠模式又稱之為靜態工廠方法,屬於建立型模式。在簡單工廠模式中,可以根據傳遞的引數不同,返回不同類的例項。簡單工廠模式定義了一個類,這個類專門用於建立其他類的例項,這些被建立的類都有一個共同的父類。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public class SimpleFactory
    {
        public static Operation GetOperation(op op, double a, double b)
        {
            switch (op)
            {
                case op.add: return new Add(a, b);
                case op.sub: return new Sub(a, b);
                case op.mul: return new Mul(a, b);
                case op.div: return new Div(a, b);
                default: return new undef(a, b);
            }
        }
    }

    public enum op
    {
        add = '+',
        sub = '-',
        mul = '*',
        div = '/'
    }

    public abstract class Operation
    {
        public double a, b;
        public Operation(double a, double b)
        {
            this.a = a;
            this.b = b;
        }
        public abstract double GetResult();
    }

    public class Add : Operation
    {
        public Add(double a, double b) : base(a, b) { }

        public override double GetResult()
        {
            return a + b;
        }
    }

    public class Sub : Operation
    {
        public Sub(double a, double b) : base(a, b) { }

        public override double GetResult()
        {
            return a - b;
        }
    }

    public class Mul : Operation
    {
        public Mul(double a, double b) : base(a, b) { }

        public override double GetResult()
        {
            return a * b;
        }
    }

    public class Div : Operation
    {
        public Div(double a, double b) : base(a, b) { }

        public override double GetResult()
        {
            try
            {
                return a / b;
            }
            catch (DivideByZeroException e)
            {
                throw e;
            }
        }
    }

    public class undef : Operation
    {
        public undef(double a, double b) : base(a, b) { }

        public override double GetResult()
        {
            throw new NotImplementedException();
        }
        
    }
}

二、工廠方法模式

模式說明

工廠方法模式定義了一個建立物件的介面,但由子類決定要例項化的類是哪一個。工廠方法模式讓例項化推遲到子類。

和簡單工廠區別在於,每個工廠只管生產自己對應的產品,而簡單工廠是一個工廠生產各種產品。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public interface ILogger
    {
        void write(string log);
    }
    public class EventLogger : ILogger
    {
        public void write(string log)
        {
            Console.WriteLine("EventLog:" + log);
        }
    }
    public class FileLogger : ILogger
    {
        public void write(string log)
        {
            Console.WriteLine("FileLog:" + log);
        }
    }

    public interface ILoggerFactory
    {
        ILogger CreateLogger();
    }
    public class EventLoggerFactory : ILoggerFactory
    {
        public ILogger CreateLogger()
        {
            return new EventLogger();
        }
    }
    public class FileLoggerFactory : ILoggerFactory
    {
        public ILogger CreateLogger()
        {
            return new FileLogger();
        }
    }
}

 三、抽象工廠模式

模式說明

抽象工廠模式提供一個介面,用於建立相關或者依賴物件的家族,而不需要明確指定具體類。

抽象工廠允許客戶端使用抽象的介面來建立一組相關的產品,而不需要關係實際產出的具體產品是什麼。這樣一來,客戶就可以從具體的產品中被解耦。

和工廠方法主要區別於,抽象工廠內要像像定義中說的一樣,‘建立一組相關的產品’。

感覺像是(不知道這樣理解對否):簡單工廠是一個工廠生產多個產品;工廠方法是拆分成子工廠,分別生產各自產品;抽象工廠整合工廠方法和簡單工廠,隨著子工廠規模變大,也可以生產多個類似產品。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    //抽象實體
    public abstract class absSalary
    {
        protected double salary;
        protected double bonus;
        protected double tax;
        public absSalary(double sal, double bns, double t)
        {
            this.salary = sal;
            this.bonus = bns;
            this.tax = t;
        }
        public abstract double CalculateTax();
    }
    public class ChineseSalary : absSalary
    {
        public ChineseSalary(double sal, double bns, double t)
            : base(sal, bns, t)
        {
        }
        public override double CalculateTax()
        {
            return (base.salary + base.bonus - 3500) * base.tax;
        }
    }
    public class ForeignerSalary : absSalary
    {
        public ForeignerSalary(double sal, double bonus, double tax)
            : base(sal, bonus, tax)
        {
        }
        public override double CalculateTax()
        {
            return (base.salary + base.bonus - 4000) * base.tax;
        }
    }

    public abstract class absSocialSecurity
    {
        protected double SocialSecurity;

        public absSocialSecurity()
        {
            this.SocialSecurity = 0;
        }
        public virtual double GetSocialSecurity()
        {
            return this.SocialSecurity;
        }
    }
    public class ChineseSocialSecurity : absSocialSecurity
    {
        public ChineseSocialSecurity(double socialsecurity)
            : base()
        {
            base.SocialSecurity = socialsecurity < 1000 ? 1000 : socialsecurity;
        }
    }
    public class ForeignerSocialSecurity : absSocialSecurity
    {
        public ForeignerSocialSecurity(double socialsecurity)
            : base()
        {
            base.SocialSecurity = socialsecurity < 1500 ? 1500 : socialsecurity;
        }
    }

    //抽象工廠,生產一系列產品(多個Create方法,分別對應不同產品)
    public interface AbstractFactory
    {
        absSalary CreateSalary(double sal, double bonus, double tax);
        absSocialSecurity CreateSocialSecurity(double socialsecurity);
    }
    public class ChineseFactory : AbstractFactory
    {
        public absSalary CreateSalary(double sal, double bonus, double tax)
        {
            return new ChineseSalary(sal, bonus, tax);
        }
        public absSocialSecurity CreateSocialSecurity(double socialsecurity)
        {
            return new ChineseSocialSecurity(socialsecurity);
        }
    }
    public class ForeignerFactory : AbstractFactory
    {
        public absSalary CreateSalary(double sal, double bonus, double tax)
        {
            return new ForeignerSalary(sal, bonus, tax);
        }
        public absSocialSecurity CreateSocialSecurity(double socialsecurity)
        {
            return new ForeignerSocialSecurity(socialsecurity);
        }
    }
}

四、建立者模式

模式說明

建造者模式將一個複雜物件的構建與表示分離,使得同樣的構建過程可以建立不同的表示。

建造者模式構建複雜物件就像造汽車一樣,是一個一個元件一個一個步驟創建出來的,它允許使用者通過制定的物件型別和內容來建立他們,但是使用者並不需要知道這個複雜物件是如何構建的,它只需要明白通過這樣做我可以得到一個完整的複雜物件例項。

和工廠方法很像,創造者是一個builder內每個方法分別建立產品零部件,而工廠方法是每個factory生產一個產品。如果把builder的零部件當做一個完整產品呢?是不是就像 builder又再一次封裝了factory~ 

模式結構圖

程式碼示例

namespace DesignPattern
{
    public class Meal
    {
        private string food;
        private string drink;
        public Meal() { }
        public void setFood(string food)
        {
            this.food = food;
        }
        public void setDrink(string drink)
        {
            this.drink = drink;
        }
        public string getFood()
        {
            return this.food;
        }
        public string getDrink()
        {
            return this.drink;
        }
    }

    //建造者,分別建造不同部件,然後返回整體
    public abstract class Builder
    {
        protected Meal meal = new Meal();
        public abstract void buildFood();
        public abstract void buildDrink();
        public Meal GetMeal()
        {
            return meal;
        }
    }

    public class MealABuilder : Builder
    {
        public override void buildFood()
        {
            meal.setFood("A food");
        }
        public override void buildDrink()
        {
            meal.setDrink("A drink");
        }
    }
    public class MealBBuilder : Builder
    {
        public override void buildFood()
        {
            meal.setFood("B food");
        }
        public override void buildDrink()
        {
            meal.setDrink("B drink");
        }
    }

    public class Waitor
    {
        public void PrepareMeal(Builder builder)
        {
            builder.buildDrink();
            builder.buildFood();
        }
    }
}

 

五、原型模式

模式說明

所謂原型模式就是用原型例項指定建立物件的種類,並且通過複製這些原型建立新的物件。

說到複製,就會有深/淺兩種複製,這是面向物件的值型別和引用型別的差異,具體不作說明

模式結構圖

程式碼示例

namespace DesignPattern
{
    [Serializable]
    public class other
    {
        public int value { get; set; }
        public other()
        {
            value = 10;
        }
    }

    [Serializable]
    public abstract class ColorPrototype
    {
        public int red { get; set; }
        public int green { get; set; }
        public int blue { get; set; }

        public other o = new other();

        //淺拷貝
        public virtual ColorPrototype Clone()
        {
            return (ColorPrototype)this.MemberwiseClone();
        }
    }

    public class Red : ColorPrototype
    {
        public override ColorPrototype Clone()
        {
            return base.Clone();
        }
    }

    [Serializable]
    public class Green : ColorPrototype
    {
        public override ColorPrototype Clone()
        {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, this);
            stream.Position = 0;
            ColorPrototype obj = (ColorPrototype)formatter.Deserialize(stream);
            return obj;
        }
    }
}

 

六、單例模式

模式說明

在它的核心結構中值包含一個被稱為單例的特殊類。一個類只有一個例項,即一個類只有一個物件例項。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public class Singleton
    {
        private int cnt = 0;
        private static Singleton instance = null;
        private volatile static Singleton safeInstance = null;
        private static readonly object lockedobj = new object();
        private Singleton()
        {
        }
        public static Singleton GetInstance()
        {
            if (instance == null) instance = new Singleton();
            return instance;
        }
        public static Singleton GetSafeInstance()
        {
            if (safeInstance == null)
            {
                lock (lockedobj)
                {
                    if (safeInstance == null)
                    {
                        safeInstance = new Singleton();
                    }
                }
            }
            return safeInstance;
        }
        public void count()
        {
            cnt += 1;
        }
        public int getCnt()
        {
            return cnt;
        }
    }

}

 


 

結構型模式

七、介面卡模式

模式說明

介面卡模式就是將一個類的介面,轉換成客戶期望的另一個介面。介面卡讓原本介面不相容的類可以合作無間。

在介面卡模式中,我們可以定義一個包裝類,包裝不相容介面的物件,這個包裝類就是介面卡,它所包裝的物件就是適配者。

介面卡提供給客戶需要的介面,介面卡的實現就是將客戶的請求轉換成對適配者的相應的介面的引用。也就是說,當客戶呼叫介面卡的方法時,介面卡方法內部將呼叫 適配者的方法,客戶並不是直接訪問適配者的,而是通過呼叫介面卡方法訪問適配者。因為介面卡可以使互不相容的類能夠“合作愉快”。

模式結構圖

程式碼示例

注:此處ILogger介面使用了【工廠方法模式】定義的介面

 

namespace DesignPattern
{
    public interface IAdaptor
    {
        void writelog(string log);
    }
    public class LogAdaptor : IAdaptor
    {
        ILogger logger;
        public LogAdaptor(ILogger logger)
        {
            this.logger = logger;
        }
        public void writelog(string log)
        {
            this.logger.write(log);
        }
    }  
}

 

八、橋接模式

模式說明

橋接模式即將抽象部分與它的實現部分分離開來,使他們都可以獨立變化。

橋接模式將繼承關係轉化成關聯關係,它降低了類與類之間的耦合度,減少了系統中類的數量,也減少了程式碼量。

個人感覺,代理模式、介面卡模式和橋接模式相類似,代理模式是一個代理對外表示一個特定的類,介面卡模式相當於一個介面卡代理多個類,而橋接模式則更加適用於多個對多個的時候

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public abstract class Color
    {
        public string name { get; set; }
    }
    public abstract class Shape
    {
        private Color color;
        public string name { get; set; }
        public void SetColor(Color c)
        {
            color = c;
        }
        public void Draw()
        {
            Console.WriteLine("draw shape {0} with color {1}", this.name, this.color.name);
        }
    }

    public class White : Color
    {
        public White()
        {
            this.name = "white";
        }
    }
    public class Blue : Color
    {
        public Blue()
        {
            this.name = "blue";
        }
    }

    public class Squre : Shape
    {
        public Squre()
        {
            this.name = "squre";
        }
    }
    public class Circle : Shape
    {
        public Circle()
        {
            this.name = "circle";
        }
    }
}

九、裝飾者模式

模式說明

裝飾者模式裝飾者模式可以動態地給一個物件增加一些額外的職責。就增加功能來說,裝飾者模式相比生成子類更為靈活。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public abstract class Car
    {
        public string color { get; set; }
        public int compartment { get; set; }
        public void run()
        {
            Console.WriteLine(color + " " + compartment + " compartment " + this.GetType().Name + "  is running!");
        }
   }
    public class Benz:Car
    {
        public Benz()
        {
            base.color = "black";
            base.compartment = 1;
        }
    }
    public class QQ:Car
    {
        public QQ()
        {
            base.color = "black";
            base.compartment = 1;
        }
    }
    public abstract class Decorator : Car
    {
        public Car car;
        public Decorator(Car car)
        {
            this.car = car;
        }
    }
    public class ColorDecorator:Decorator
    {
        //一般在建構函式內完成屬性的修改(裝飾),這裡單獨加了一個decorate方法
        public ColorDecorator(Car car):base(car)
        {
        }
        public Car decorate(string color)
        {
            base.car.color = color;
            return base.car;
        }
    }

    public class CompartmentDecorator : Decorator
    {
        public CompartmentDecorator(Car car)
            : base(car)
        {
        }
        public Car decorate(int compartment)
        {
            base.car.compartment = compartment;
            return base.car;
        }
    }
}

 

 十、組合模式

模式說明

組合模式組合多個物件形成樹形結構以表示“整體-部分”的結構層次。

組合模式對單個物件(葉子物件)和組合物件(組合物件)具有一致性,它將物件組織到樹結構中,可以用來描述整體與部分的關係。同時它也模糊了簡單元素(葉 子物件)和複雜元素(容器物件)的概念,使得客戶能夠像處理簡單元素一樣來處理複雜元素,從而使客戶程式能夠與複雜元素的內部結構解耦。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public abstract class File
    {
        protected string name;
        public File(string name)
        {
            this.name = name;
        }
        public abstract void Display();
    }
    public class Folder : File
    {
        IList<File> list;
        public Folder(string name)
            : base(name)
        {
            list = new List<File>();
        }
        public void AddFile(File file)
        {
            list.Add(file);
        }
        public void RemoveFile(File file)
        {
            list.Remove(file);
        }
        public override void Display()
        {
            Console.WriteLine("folder:" + this.name);
            foreach (File f in list)
            {
                f.Display();
            }
        }
    }
    public class ImageFile : File
    {
        public ImageFile(string name)
            : base(name)
        {
        }
        public override void Display()
        {
            Console.WriteLine("ImageFile:" + this.name);
        }
    }
}

 

十一、外觀模式

模式說明

所謂外觀模式就是提供一個統一的介面,用來訪問子系統中的一群介面。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public class Facade
    {
        Light _light = new Light();
        TV _tv = new TV();
        public void off()
        {
            _light.on();
            _tv.off();
        }
        public void on()
        {
            _tv.on();
            _light.off();
        }
    }
    class Light
    {
        public void on()
        {
            Console.WriteLine("light on!");
        }
        public void off()
        {
            Console.WriteLine("light off!");
        }
    }
    class TV
    {
        public void on()
        {
            Console.WriteLine("tv on!");
        }
        public void off()
        {
            Console.WriteLine("tv off!");
        }
    }
}

 

十二、享元模式

模式說明

所謂享元模式就是執行共享技術有效地支援大量細粒度物件的複用。系統使用少量物件,而且這些都比較相似,狀態變化小,可以實現物件的多次複用。

FlyweightFactory內定義的實體是不變的(共享的),傳入引數是狀態變化。

快取形式,傳入引數已經被快取則直接返回,否則建立引數對應實體,放入快取並返回該新實體

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public class FlyweightFactory
    {
        static Dictionary<string, IFlyweight> pendic = new Dictionary<string, IFlyweight>();
        public IFlyweight getPen(string color)
        {
            if (pendic.ContainsKey(color))
            {
                return pendic[color];
            }
            else
            {
                IFlyweight pen = new ConcreteFlyweight(color);
                pendic.Add(color, pen);
                return pen;
            }
        }
        public void Display()
        {
            foreach (KeyValuePair<string,IFlyweight> pair in pendic)
            {
                Console.WriteLine(pair.Value.GetType().FullName + ":" + pair.Key);
            }
        }
    }

    public interface IFlyweight
    {
        string GetColor();
    };
    public class ConcreteFlyweight : IFlyweight
    {
        string color;
        public ConcreteFlyweight(string color)
        {
            this.color = color;
        }
        public string GetColor()
        {
            return this.color;
        }
    }
}

 

十三、代理模式

模式說明

代理模式就是給一個物件提供一個代理,並由代理物件控制對原物件的引用。

在代理模式中,“第三者”代理主要是起到一箇中介的作用,它連線客戶端和目標物件。

 模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public class Girl
    {
        public string name { get; set; }
        public Girl(string name)
        {
            this.name = name;
        }
    }
    public class Boy
    {
        private Girl girl;
        public string name { get; set; }
        public Boy(string name, Girl girl)
        {
            this.name = name;
            this.girl = girl;
        }
        public void GiveFlower()
        {
            Console.WriteLine("boy {0} give flower to girl {1}", this.name, this.girl.name);
        }
    }
    public class Proxy
    {
        private Boy boy;
        public Proxy(Boy boy)
        {
            this.boy = boy;
        }
        public void GiveFlower()
        {
            this.boy.GiveFlower();
        }
    }
}

 


 

行為型模式

十四、迭代器模式

模式說明

提供一種方法順序訪問一個聚合物件中各個元素, 而又無須暴露該物件的內部表示

這種模式用於順序訪問集合物件的元素,不需要知道集合物件的底層表示。

 模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public class Persons : IEnumerable
    {
        string[] m_Names;

        public Persons(params string[] Names)
        {
            m_Names = new string[Names.Length];

            Names.CopyTo(m_Names, 0);
        }

        public IEnumerator GetEnumerator()
        {
            foreach (string s in m_Names)
            {
                yield return s;
            }
        }

        public int Length { get { return m_Names.Length; } }

        public string this[int i]
        {
            get
            {
                return m_Names[i];
            }
            set
            {
                m_Names[i] = value;
            }
        }
    }


}

 

十五、直譯器模式

模式說明

所謂直譯器(Interpreter)就是將一系列指令轉化成程式碼,能夠執行的程式碼。Interpreter本來就有翻譯的意思。GoF給它的定義是:給定一個語言,定義它的文法的一種表示,並定義一個直譯器,這個直譯器使用該表示來解釋語言中的句子。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public class Context
    {
        private string msg;
        public Context(string msg)
        {
            this.msg = msg;
        }
        public string GetMsg()
        {
            return this.msg;
        }
    }
    public interface Interpreter
    {
        string Interprete(Context context);
    }
    public class UpperInterpreter : Interpreter
    {
        public string Interprete(Context context)
        {
            string msg = context.GetMsg();
            return msg.ToUpperInvariant();
        }
    }
    public class LowerInterpreter : Interpreter
    {
        public string Interprete(Context context)
        {
            string msg = context.GetMsg();
            return msg.ToLowerInvariant();
        }
    }
}

十六、命令模式

模式說明

將請求封裝成物件,從而使可用不同的請求對客戶進行引數化;對請求排隊或記錄請求日誌,以及支援可撤消的操作。

模式結構圖

程式碼示例

 

 

namespace DesignPattern
{
    //接受命令的物件
    public class CDMachine
    {
        public void on()
        {
            Console.WriteLine("CD Machine turns on!");
        }
        public void off()
        {
            Console.WriteLine("CD Machine turns off!");
        }
    }
    //定義命令
    public abstract class Command
    {
        public abstract void Execute(CDMachine cdMachine);
    }
    public class TurnonCommand : Command
    {
        public override void Execute(CDMachine cdMachine)
        {
            cdMachine.on();
        }
    }
    public class TurnoffCommand : Command
    {
        public override void Execute(CDMachine cdMachine)
        {
            cdMachine.off();
        }
    }
    //傳送命令的物件
    public class Controller
    {
        //遙控的功能 --- 可傳送的命令
        private TurnonCommand turnonCommand;
        private TurnoffCommand turnoffCommand;
        public Controller(TurnonCommand turnonCommand, TurnoffCommand turnoffCommand)
        {
            this.turnonCommand = turnonCommand;
            this.turnoffCommand = turnoffCommand;
        }

        public void turnOn(CDMachine cdMachine)
        {
            this.turnonCommand.Execute(cdMachine);
        }
        public void turnOff(CDMachine cdMachine)
        {
            this.turnoffCommand.Execute(cdMachine);
        }
    }
}

十七、中介者模式

模式說明

所謂中介者模式就是用一箇中介物件來封裝一系列的物件互動,中介者使各物件不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的互動。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public abstract class Person
    {
        public string name;
        public Mediator mediator;
        public Person(string name, Mediator mediator)
        {
            this.name = name;
            this.mediator = mediator;
        }
        public void Contact(string msg)
        {
            //引數 this 代表 訊息來自我
            this.mediator.SendMsg(msg, this);
        }

        internal void GetMsg(string msg)
        {
            Console.WriteLine(this.name + " 收到訊息:" + msg);
        }
    }
    public class HouseOwner : Person
    {
        public HouseOwner(string name, Mediator mediator) : base(name, mediator) { }
    }
    public class Tenant : Person
    {
        public Tenant(string name, Mediator mediator) : base(name, mediator) { }
    }

    public interface Mediator
    {
        void SendMsg(string msg, Person p);
    }
    public class ConcreteMediator : Mediator
    {
        HouseOwner houseOwner;
        Tenant tenant;
        public ConcreteMediator()
        {
        }
        public void SetHouseOwner(HouseOwner houseOwner)
        {
            this.houseOwner = houseOwner;
        }
        public void SetTenant(Tenant tenant)
        {
            this.tenant = tenant;
        }
        public void SendMsg(string msg, Person p)
        {
            if (p.GetType() == houseOwner.GetType())
            {
                tenant.GetMsg(msg);
            }
            else
            {
                houseOwner.GetMsg(msg);
            }
        }
    }
}

十八、備忘錄模式

模式說明

所謂備忘錄模式就是在不破壞封裝的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態,這樣可以在以後將物件恢復到原先儲存的狀態。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public class Memonto
    {
        public int blood { get; set; }
        public int magic { get; set; }
    }
    public class Caretaker
    {
        private Memonto memonto;
        public void SetMemonto(Memonto memonto)
        {
            this.memonto = memonto;
        }
        public Memonto getMemonto()
        {
            return this.memonto;
        }
    }

    public class Original
    {
        public int blood { get; set; }
        public int magic { get; set; }
        public Memonto SaveMemonto()
        {
            return new Memonto() { blood = this.blood, magic = this.magic };
        }
        public void RestoreMemonto(Memonto memonto)
        {
            this.blood = memonto.blood;
            this.magic = memonto.magic;
        }
        public void display()
        {
            Console.WriteLine("blood:" + this.blood + "\tmagic:" + this.magic);
        }
    }
}

十九、觀察者模式

模式說明

定義了一種一對多的關係,讓多個觀察物件同時監聽一個主題物件,當主題物件狀態發生變化時會通知所有觀察者。

模式結構圖

程式碼示例

public interface Observer
    {
        void Update(Subject subject);
    }
    public abstract class Subject
    {
        List<Observer> obsList = new List<Observer>();
        public void AddObserver(Observer observer)
        {
            obsList.Add(observer);
        }
        public void RemoveObserver(Observer observer)
        {
            obsList.Remove(observer);
        }
        public void notity()
        {
            foreach (Observer o in obsList)
            {
                o.Update(this);
            }
        }
        private string _state;
        public void SetState(string state)
        {
            this._state = state;
        }
        public string GetState()
        {
            return this._state;
        }
    }
    public class ConcreteSubject : Subject
    {
    }
    public class ConcreteObserver1 : Observer
    {
        public void Update(Subject subject)
        {
            Console.WriteLine("ConcreteObserver1 get notice:" + subject.GetState());
        }
    }
    public class ConcreteObserver2 : Observer
    {
        public void Update(Subject subject)
        {
            Console.WriteLine("ConcreteObserver2 get notice:" + subject.GetState());
        }
    }

 

 

//事件委託的方式
    public delegate void updateDelegate(Subject subject);

    public class EventSubjet : Subject
    {
        public event updateDelegate UpdateHandler;
        public void EventNotify()
        {
            OnUpdate();
        }
        private void OnUpdate()
        {
            if (UpdateHandler != null)
            {
                UpdateHandler(this);
            }
        }
    }

 

二十、狀態模式

模式說明

當一個物件的內在狀態改變時允許改變其行為,這個物件看起來像是改變了其類。

模式結構圖

程式碼示例

namespace DesignPattern
{
    public interface IState
    {
        void display();
    }
    public class WorkState:IState
    {
        public void display()
        {
            Console.WriteLine("Working State");
        }
    }
    public class RestState:IState
    {
        public void display()
        {
            Console.WriteLine("Rest State");
        }
    }

    public class Programmer
    {
        IState _state;
        public void Doing(DateTime dt)
        {
            if(dt.Hour<7 || dt.Hour > 22)
            {
                _state = new RestState();
            }
            else
            {
                _state = new WorkState();
            }
            _state.display();
        }
    }
}

二十一、模板模式

模式說明

定義一個操作中的演算法的骨架,而將步驟延遲到子類中。模板方法使得子類可以不改變一個演算法的結構即可重定義演算法的某些特定步驟。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public abstract class Template
    {
        protected void boilWater()
        {
            Console.WriteLine("boil water");
        }
        protected virtual void brew()
        {
            Console.WriteLine("brew");
        }
        protected void pourInCup()
        {
            Console.WriteLine("pour into cup");
        }
        protected virtual void addOther()
        {
            Console.WriteLine("add other");
        }
        public void makeBeverage()
        {
            boilWater();
            brew();
            pourInCup();
            addOther();
        }
    }
    public class Tea : Template
    {
        protected override void brew()
        {
            Console.WriteLine("tea");
        }
        protected override void addOther()
        {
            Console.WriteLine("add lemon");
        }
    }
    public class Coffee : Template
    {
        protected override void brew()
        {
            Console.WriteLine("coffee");
        }
        protected override void addOther()
        {
            Console.WriteLine("add sugar");
        }
    }
}

二十二、策略模式

模式說明

定義演算法家族並且分別封裝,它們之間可以相互替換而不影響客戶端。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public abstract class OrderStrategy
    {
        public List<int> orderList;
        public abstract void Order();
        public void display()
        {
            foreach (int i in orderList)
            {
                Console.Write(i + "\t");
            }
            Console.WriteLine();
        }
    }
    public class BubbleStrategy : OrderStrategy
    {
        public override void Order()
        {
            for (int i = 0; i < orderList.Count; i++)
            {
                for (int j = i + 1; j < orderList.Count; j++)
                {
                    if (orderList[i] < orderList[j])//冒泡降序 小的冒上去
                    {
                        int temp = orderList[i];
                        orderList[i] = orderList[j];
                        orderList[j] = temp;
                    }
                }
            }
        }
    }
    public class SelectionStrategy : OrderStrategy
    {
        public override void Order()
        {
            for (int i = 0; i < orderList.Count; i++)
            {
                int smallvalue = orderList[i];
                int smallposition = i;
                for (int j = i + 1; j < orderList.Count; j++)
                {
                    if (orderList[j] < smallvalue)
                    {
                        smallposition = j;
                        smallvalue = orderList[j];
                    }
                }
                //將最小值放到當前要排序的位置
                orderList[smallposition] = orderList[i];
                orderList[i] = smallvalue;
            }
        }
    }
    public class InsertionStrategy : OrderStrategy
    {
        public override void Order()
        {
            for (int i = 1; i < orderList.Count; i++)
            {
                int temp = orderList[i];//當前要插入的值,相當於位置I是個空白位置,供對比進行後移
                int j = i;
                //j之前的序列已經排序好,選一個位置把當前值插入
                
                while (j > 0)
                {
                    //i從1開始,是因為這裡j要比較前一個值
                    if (temp < orderList[j - 1]) //插入過程中,每次比較的值大於當前值則向後移動
                    {
                        orderList[j] = orderList[j-1];
                        j--;
                    }
                    else
                    {
                        break;
                    }
                }
                //找到位置(break)或者迴圈正常結束(說明當前值最小)則賦值。
                orderList[j] = temp;
            }
        }
    }

    public class StrategyManager
    {
        OrderStrategy strategy;
        public void SetStrategy(OrderStrategy strategy)
        {
            this.strategy =strategy;
        }
        public void Sort(List<int> list)
        {
            this.strategy.orderList = list;
            this.strategy.Order();
            this.strategy.display();
        }
    }
}

二十三、訪問者模式

模式說明

訪問者模式即表示一個作用於某物件結構中的各元素的操作,它使我們可以在不改變各元素的類的前提下定義作用於這些元素的新操作。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public interface Element
    {
        void accept(Visitor visitor);
    }
    public class ConcreteElementA : Element
    {
        string name;
        public void SetName(string name)
        {
            this.name = name;
        }
        public string GetName()
        {
            return this.name;
        }
        public void accept(Visitor visitor)
        {
            visitor.visitElementA(this);
        }
    }
    public class ConcreteElementB : Element
    {
        int ID;
        public void SetID(int id)
        {
            this.ID = id;
        }
        public int GetID()
        {
            return this.ID;
        }
        public void accept(Visitor visitor)
        {
            visitor.visitElementB(this);
        }
    }

    public interface Visitor
    {
        void visitElementA(ConcreteElementA ea);
        void visitElementB(ConcreteElementB eb);
    }
    public class ConcreteVisitorA : Visitor
    {
        public void visitElementA(ConcreteElementA ea)
        {
            Console.WriteLine("ConcreteVisitorA visit ElemantA:" + ea.GetName());
        }
        public void visitElementB(ConcreteElementB eb)
        {
            Console.WriteLine("ConcreteVisitorA visit ElemantB:" + eb.GetID());
        }
    }
    public class ConcreteVisitorB : Visitor
    {
        public void visitElementA(ConcreteElementA ea)
        {
            Console.WriteLine("ConcreteVisitorB visit ElemantA:" + ea.GetName());
        }
        public void visitElementB(ConcreteElementB eb)
        {
            Console.WriteLine("ConcreteVisitorB visit ElemantB:" + eb.GetID());
        }
    }

    public class objectStructure
    {
        List<Element> elementlist = new List<Element>();
        public void Attach(Element e)
        {
            elementlist.Add(e);
        }
        public void Dettach(Element e)
        {
            elementlist.Remove(e);
        }
        public void Accept(Visitor visit)
        {
            foreach(Element e in elementlist)
            {
                e.accept(visit);
            }
        }
    }
}

 

二十四、責任鏈模式

模式說明

避免請求傳送者與接收者耦合在一起,讓多個物件都有可能接收請求,將這些物件連線成一條鏈,並且沿著這條鏈傳遞請求,直到有物件處理它為止,這就是職責鏈模式。

模式結構圖

程式碼示例

 

namespace DesignPattern
{
    public class Request
    {
        int days;
        string name;
        public Request(int days, string name)
        {
            this.days = days;
            this.name = name;
        }
        public int GetDays()
        {
            return days;
        }
        public string GetName()
        {
            return name;
        }

    }
    public abstract class Responsibility
    {
        protected Responsibility responsibility;
        public Responsibility(Responsibility responsibility)
        {
            this.responsibility = responsibility;
        }
        public abstract void HandleRequest(Request request);
    }
    public class Leader : Responsibility
    {
        public Leader(Responsibility responsibility)
            : base(responsibility)
        { }
        public override void HandleRequest(Request request)
        {
            if (request.GetDays() < 3)
            {
                Console.WriteLine("Leader passed {0}'s {1} days request", request.GetName(), request.GetDays());
            }
            else
            {
                this.responsibility.HandleRequest(request);
            }
        }
    }

    public class Department : Responsibility
    {
        public Department(Responsibility responsibility)
            : base(responsibility)
        { }
        public override void HandleRequest(Request request)
        {
            if (request.GetDays() < 8)
            {
                Console.WriteLine("Department passed {0}'s {1} days request", request.GetName(), request.GetDays());
            }
            else
            {
                this.responsibility.HandleRequest(request);
            }
        }
    }
    //責任鏈終端必須處理
    public class Boss : Responsibility
    {
        public Boss() : base(null) { }
        public override void HandleRequest(Request request)
        {
            if (request.GetDays() < 15)
            {
                Console.WriteLine("Boss passed {0}'s {1} days request", request.GetName(), request.GetDays());
            }
            else
            {
                Console.WriteLine("Boss refused {0}'s {1} days request", request.GetName(), request.GetDays());
            }
        }
    }
}

 

 

 主程式(注:呼叫順序與該列表順序不一致)


namespace DesignPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            //簡單工廠
            Console.WriteLine("簡單工廠");
            Console.WriteLine(SimpleFactory.GetOperation(op.add, 1.1, 2.2).GetResult());

            //工廠方法
            Console.WriteLine("\n工廠方法");
            ILoggerFactory factorymethod = new EventLoggerFactory();
            ILogger iLogger = factorymethod.CreateLogger();
            iLogger.write("123");

            factorymethod = new FileLoggerFactory();
            iLogger = factorymethod.CreateLogger();
            iLogger.write("321");

            //抽象工廠
            Console.WriteLine("\n抽象工廠");
            AbstractFactory absFactory = new ChineseFactory();
            absSalary chSalary = absFactory.CreateSalary(10000, 8000, 0.12);
            absSocialSecurity chScSc = absFactory.CreateSocialSecurity(1200);
            Console.WriteLine(chSalary.CalculateTax());
            Console.WriteLine(chScSc.GetSocialSecurity());

            absFactory = new ForeignerFactory();
            chSalary = absFactory.CreateSalary(10000, 8000, 0.12);
            chScSc = absFactory.CreateSocialSecurity(1200);
            Console.WriteLine(chSalary.CalculateTax());
            Console.WriteLine(chScSc.GetSocialSecurity());

            //創造者模式
            Console.WriteLine("\n創造者模式");
            Waitor waiter = new Waitor();
            Builder b1 = new MealABuilder();
            Builder b2 = new MealBBuilder();

            waiter.PrepareMeal(b1);
            Meal ma = b1.GetMeal();
            Console.WriteLine(ma.getFood() + "\t" + ma.getDrink());

            waiter.PrepareMeal(b2);
            Meal mb = b2.GetMeal();
            Console.WriteLine(mb.getFood() + "\t" + mb.getDrink());

            //原型模式
            Console.WriteLine("\n原型模式");
            Red r = new Red();
            r.o.value = 20;//改變引用值
            ColorPrototype RCopy = r.Clone();
            RCopy.o.value = 30;
            Console.WriteLine(r.o.value);//30 淺拷貝,指向同一個應用物件,一處改變,都改變

            Green g = new Green();
            g.o.value = 20;
            ColorPrototype GCopy = g.Clone();
            GCopy.o.value = 30;
            Console.WriteLine(g.o.value);//20 深拷貝,引用物件獨立

            //單例模式
            Console.WriteLine("\n單例模式");
            Task[] tArr = new Task[]{
            Task.Run(() => Singleton.GetInstance().count()),
            Task.Run(() => Singleton.GetInstance().count()),
            Task.Run(() => Singleton.GetInstance().count()),
            Task.Run(() => Singleton.GetInstance().count()),
            Task.Run(() => Singleton.GetInstance().count()),
            Task.Run(() => Singleton.GetInstance().count()),
            Task.Run(() => Singleton.GetInstance().count()),
            Task.Run(() => Singleton.GetInstance().count()),
            Task.Run(() => Singleton.GetInstance().count()),
            Task.Run(() => Singleton.GetInstance().count())
            };
            Singleton.GetInstance().count();
            Task.WaitAll(tArr);
            Console.WriteLine("danger:" + Singleton.GetInstance().getCnt());

            Task[] tArrSafe = new Task[]{
            Task.Run(() => Singleton.GetSafeInstance().count()),
            Task.Run(() => Singleton.GetSafeInstance().count()),
            Task.Run(() => Singleton.GetSafeInstance().count()),
            Task.Run(() => Singleton.GetSafeInstance().count()),
            Task.Run(() => Singleton.GetSafeInstance().count()),
            Task.Run(() => Singleton.GetSafeInstance().count()),
            Task.Run(() => Singleton.GetSafeInstance().count()),
            Task.Run(() => Singleton.GetSafeInstance().count()),
            Task.Run(() => Singleton.GetSafeInstance().count()),
            Task.Run(() => Singleton.GetSafeInstance().count())
            };
            Singleton.GetSafeInstance().count();
            Task.WaitAll(tArrSafe);
            Console.WriteLine("safe:" + Singleton.GetSafeInstance().getCnt());

            //迭代器
            Console.WriteLine("\n迭代器");
            Persons ps = new Persons(new string[] { "1", "2", "3" });
            foreach (string name in ps)
            {
                Console.WriteLine(name);
            }
            for (var i = 0; i < ps.Length; i++)
            {
                Console.WriteLine(ps[i]);
            }

            //介面卡模式
            Console.WriteLine("\n介面卡模式");
            EventLogger eLog = new EventLogger();
            FileLogger fLog = new FileLogger();
            LogAdaptor adapter = new LogAdaptor(eLog);
            adapter.writelog("123123");
            adapter = new LogAdaptor(fLog);
            adapter.writelog("123123");

            //代理模式
            Console.WriteLine("\n代理模式");
            Girl girl = new Girl("Han MeiMei");
            Boy boy = new Boy("Li Lei", girl);
            Proxy proxy = new Proxy(boy);
            proxy.GiveFlower();

            //橋接模式
            Console.WriteLine("\n橋接模式");
            Color blue = new Blue();
            Color white = new White();
            Shape squre = new Squre();
            Shape circle = new Circle();
            squre.SetColor(blue);
            squre.Draw();
            circle.SetColor(white);
            circle.Draw();

            //組合模式
            Console.WriteLine("\n組合模式");
            Folder folder1 = new Folder("study");
            File img = new ImageFile("img");
            folder1.AddFile(img);
            Folder folder2 = new Folder("c#");
            folder2.AddFile(img);
            folder1.AddFile(folder2);
            folder1.Display();

            //直譯器模式
            Console.WriteLine("\n直譯器模式");
            Context context = new Context("ABcdeFG");
            UpperInterpreter ui = new UpperInterpreter();
            string inprResut = ui.Interprete(context);
            Console.WriteLine("up:" + inprResut);

            LowerInterpreter li = new LowerInterpreter();
            inprResut = li.Interprete(context);
            Console.WriteLine("low:" + inprResut);

            //外觀模式
            Console.WriteLine("\n外觀模式");
            Facade facade = new Facade();
            Console.WriteLine("電視開啟,電燈關閉!");
            facade.on();
            Console.WriteLine("3秒後電燈開啟,電視關閉");
            Thread.Sleep(3000);
            facade.off();

            //享元模式
            Console.WriteLine("\n享元模式");
            FlyweightFactory flyfactory = new FlyweightFactory();
            IFlyweight flyweidht = flyfactory.getPen("red");
            Console.WriteLine(flyweidht.GetColor());
            flyweidht = flyfactory.getPen("blue");
            Console.WriteLine(flyweidht.GetColor());
            flyweidht = flyfactory.getPen("red");
            Console.WriteLine(flyweidht.GetColor());
            flyfactory.Display();

            //責任鏈模式
            Console.WriteLine("\n責任鏈模式");
            Request request = new Request(20, "wang");
            Boss boss = new Boss();
            Department department = new Department(boss);
            Leader leader = new Leader(department);
            leader.HandleRequest(request);

            //命令模式
            Console.WriteLine("\n命令模式");
            CDMachine cd = new CDMachine();
            TurnoffCommand off = new TurnoffCommand();
            TurnonCommand on = new TurnonCommand();
            Controller ctrl = new Controller(on, off);
            //遙控器傳送命令到cd機
            ctrl.turnOn(cd);
            ctrl.turnOff(cd);

            //中介者模式
            Console.WriteLine("\n中介者模式");
            //中介單獨存在
            //Mediator mediator = new ConcreteMediator();
            ConcreteMediator mediator = new ConcreteMediator();
            //房主和租客尋找中介
            HouseOwner houseOwner = new HouseOwner("houseowner", mediator);
            Tenant tenant = new Tenant("tenant", mediator);
            //中介給他們搭建連結
            mediator.SetHouseOwner(houseOwner);
            mediator.SetTenant(tenant);

            houseOwner.Contact("出租房");
            tenant.Contact("租房");

            //備忘錄模式
            Console.WriteLine("\n備忘錄模式");
            Caretaker caretaker = new Caretaker();
            Original original = new Original();
            original.blood = 100;
            original.magic = 100;
            original.display();
            caretaker.SetMemonto(original.SaveMemonto());
            original.blood = 50;
            original.magic = 50;
            original.display();
            original.RestoreMemonto(caretaker.getMemonto());
            original.display();

            //觀察者模式
            Console.WriteLine("\n觀察者模式");
            Subject subject = new ConcreteSubject();
            subject.SetState("start");
            Observer o1 = new ConcreteObserver1();
            Observer o2 = new ConcreteObserver2();
            subject.AddObserver(o1);
            subject.AddObserver(o2);
            subject.notity();
            subject.SetState("change");
            subject.notity();

            //Subject eventSubject = new EventSubjet();
            EventSubjet eventSubject = new EventSubjet();
            eventSubject.UpdateHandler += o1.Update;
            eventSubject.UpdateHandler += o2.Update;
            eventSubject.SetState("event");
            eventSubject.EventNotify();

            //狀態模式
            Console.WriteLine("\n狀態模式");
            Programmer programmer = new Programmer();
            Console.WriteLine(DateTime.Now + "程式設計師正在做什麼呢?");
            programmer.Doing(DateTime.Now);
            Console.WriteLine(DateTime.Now.AddHours(-10) + "程式設計師正在做什麼呢?");
            programmer.Doing(DateTime.Now.AddHours(-10));

            //策略模式
            Console.WriteLine("\n策略模式");
            BubbleStrategy bubble = new BubbleStrategy();
            SelectionStrategy selection = new SelectionStrategy();
            InsertionStrategy insertion = new InsertionStrategy();
            
            var list = new List<int>() { 3, 1, 6, 2, 5 };
            StrategyManager manager = new StrategyManager();
            manager.SetStrategy(bubble);
            manager.Sort(list);
            manager.SetStrategy(selection);
            manager.Sort(list);
            manager.SetStrategy(insertion);
            manager.Sort(list);

            //模板模式
            Console.WriteLine("\n模板模式");
            Template tea = new Tea();
            tea.makeBeverage();
            Template coffee = new Coffee();
            coffee.makeBeverage();

            //訪問者模式
            Console.WriteLine("\n訪問者模式");
            ConcreteElementA elementA = new ConcreteElementA();
            elementA.SetName("ea");
            ConcreteElementB elementB = new ConcreteElementB();
            elementB.SetID(2);
            objectStructure structure = new objectStructure();
            structure.Attach(elementA);
            structure.Attach(elementB);

            Visitor visitorA = new ConcreteVisitorA();
            Visitor visitorB = new ConcreteVisitorB();

            structure.Accept(visitorA);
            structure.Accept(visitorB);

            //裝飾者模式
            Console.WriteLine("\n裝飾者模式");
            Car car = new Benz();
            car = new ColorDecorator(car).decorate("red");
            car.run();
            car = new CompartmentDecorator(car).decorate(3);
            car.run();
        }
    }
}

該博文出發點是使用面向物件的語言,使用簡單的示例簡要概括說明各個模式的應用,已備不時之需。

文章對原文做了些許的補充,原文地址:https://www.cnblogs.com/cotton/p/4362782.html