面試問到這個··答不出來就是沒有架構能力···這裡學習一下···面試的時候直接讓我說出26種設計模式··當時就懵逼了··我記得好像之前看的時候是23種的 還有3個是啥的··· 這裡先列出幾種創建型模式,工廠、抽象工廠、單例,建造者、原型,後續在更新 工廠模式:缺點是每增加一個類型就得增加一個工具類和 ...
面試問到這個··答不出來就是沒有架構能力···這裡學習一下···面試的時候直接讓我說出26種設計模式··當時就懵逼了··我記得好像之前看的時候是23種的 還有3個是啥的···
這裡先列出幾種創建型模式,工廠、抽象工廠、單例,建造者、原型,後續在更新
工廠模式:缺點是每增加一個類型就得增加一個工具類和對象工廠類(反射可以避免修改這個···)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection; namespace ExercisePrj.Dsignmode { public class ShapeFactory { public static IShape CtreateShape(string shape) { if (shape == "Line") { return new Line(); } else if (shape == "Circle") { return new Circle(); } return null; }
//反射的實現方式,規定一個統一的類命名方式,通過反射初始化 public static IShape CtreateWithReflection(string shape) { Assembly assembly = Assembly.GetExecutingAssembly(); var ishape = assembly.CreateInstance("ExercisePrj.Dsignmode."+shape); return ishape as IShape; } } public interface IShape { void Draw(); } public class Line: IShape { public void Draw()//隱式封閉實現,子類可以隱藏不能重寫,類調用會執行這個 { Console.WriteLine("draw line"); } void IShape.Draw()//顯示實現,介面調用會執行這個 { Console.WriteLine("IShape.DrawLine"); } } public class Circle:IShape { public void Draw() { Console.WriteLine("draw Circle"); } } }
抽象工廠模式,簡單講就是比上邊更流弊的工廠模式···這裡有用到上邊的類型
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ExercisePrj.Dsignmode { //抽象工廠類 public abstract class AbstractFactory { public abstract IShape GetShape(string shape); public abstract IColor GetColor(string color); } //工廠類子類 public class ShapeFactoryEx:AbstractFactory { public override IShape GetShape(string shape) { return ShapeFactory.CtreateShape(shape);//偷個懶 } public override IColor GetColor(string color) { return null; } } public class ColorFactory : AbstractFactory { public override IShape GetShape(string shape) { return null; } public override IColor GetColor(string color) { if(color=="blue") { return new Blue(); } else if (color=="red") { return new Red(); } return null; } } //工廠創造器 public class FactoryProducer { public static AbstractFactory getFactory( string SType) { if(SType=="shape") { return new ShapeFactoryEx(); } else if(SType=="color") { return new ColorFactory(); } return null; } } public interface IColor { void Fill(); } public class Blue:IColor { public void Fill() { Console.WriteLine("Blue"); } } public class Red : IColor { public void Fill() { Console.WriteLine("Red"); } } }
單例模式:平時用的時候連鎖都沒加···上次面試的時候,人家問在多線程裡邊會出啥問題···當時就沒反應過來·,說這有啥問題的·都是一個對象調方法就是··完事才想起來,如果初始化的函數在多線程裡邊就是線程不安全了··簡直矇蔽··這裡列好幾種寫法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ExercisePrj.Dsignmode { public class Singleton { private Singleton() { } //private static Singleton m_Singleton; //private static readonly object lockvalue = new object(); //public static Singleton GetInstance() //{ // //return m_Singleton ?? new Singleton();//不加鎖 線程不安全 // if (m_Singleton == null) // { // lock (lockvalue)//枷鎖//這裡還可以加雙鎖,就是在裡邊判斷是不是空 // { // return new Singleton(); // } // } // return m_Singleton; //} public static readonly Singleton Instance = new Singleton();//據說這個是最流弊的寫法··跟下邊的寫法是一個意思·· //public static readonly Singleton Instance=null //static Singleton() //{ // Instance = new Singleton(); //} } }
建造者模式,將一個複雜的構造與其表示分開,使用同樣的構建創建不同的表示··感覺就是做了可變動的組合,然後用一個類去構造這個變動組合類,一邊排列組型或者菜單之類的應用場景都適合
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ExercisePrj.Dsignmode { //構建類 public class MealBuilder { public Meal prepareVegMeal() { Meal meal = new Meal(); meal.addItem(new VegBurger()); meal.addItem(new Coke()); return meal; } public Meal prepareNonVegMeal() { Meal meal = new Meal(); meal.addItem(new ChickenBurger()); meal.addItem(new Pepsi()); return meal; } } //實體介面 public interface Item { string name { get;} float price { get; } IPacking packing(); } //實體關聯介面 public interface IPacking { string pack(); } //不同實體 public class Wrapper:IPacking { public string pack() { return "Wrapper"; } } public class Bottle:IPacking { public string pack() { return "Bottle"; } } public abstract class Burger:Item { public IPacking packing() { return new Wrapper(); } public abstract string name { get; } public abstract float price { get; } } public abstract class ColdDrink:Item { public IPacking packing() { return new Bottle(); } public abstract string name { get; } public abstract float price { get; } } public class VegBurger:Burger { public override string name { get; } public override float price { get; } public VegBurger() { name = "Veg Burger"; price = 25.0f; } } public class ChickenBurger: Burger { public override string name { get; } public override float price { get; } public ChickenBurger() { name = "Chicken Burger"; price = 50.0f; } } public class Coke : ColdDrink { public override string name { get; } public override float price { get; } public Coke() { name = "Coke"; price = 30.0f; } } public class Pepsi : ColdDrink { public override string name { get; } public override float price { get; } public Pepsi() { name = "Pepsi"; price = 35.0f; } } //不同的組合類 public class Meal { private List<Item> Items = new List<Item>(); public void addItem(Item item) { Items.Add(item); } public float getCost() { float cost = 0; foreach(var item in Items) { cost += item.price; } return cost; } public void ShowItems() { foreach(var item in Items) { Console.WriteLine("name={0},packing={1},price={2}", item.name, item.packing().pack(), item.price); } } } }
原型模式,就是克隆··是為了避免創建新對象,採用克隆的方式··,講道理一般實現的克隆是直接new對象然後賦值,這也沒法避免啊···,java好像有支持直接深複製的object介面··可以直接調用··python也有類似的deepcopy, C#好像沒有這個····這裡是在網上查的用序列化和反序列的方式實現深複製,這樣不用new對象···
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; namespace ExercisePrj.Dsignmode { // public class ApplianceCach { private static Dictionary<string, Appliance> ApplianceMap = new Dictionary<string, Appliance>(); public static Appliance GetApplicance(string shapeId) { Appliance cachAppliance = ApplianceMap[shapeId]; return (Appliance)cachAppliance.Clone(); } public static void loadCache() { Fridge fridge = new Fridge(); fridge.ID = "1"; ApplianceMap.Add(fridge.ID, fridge); Television tv = new Television(); tv.ID = "2"; ApplianceMap.Add(tv.ID, tv); } } [Serializable] public abstract class Appliance:ICloneable { protected string type; private string id; public string Type { get { return type; } } public string ID { get { return id; } set { id = value; } } public abstract void DoWork(); public object Clone() { object obj = null; //將對象序列化成記憶體中的二進位流 BinaryFormatter inputFormatter = new BinaryFormatter(); MemoryStream inputStream; using (inputStream = new MemoryStream()) { inputFormatter.Serialize(inputStream, this); } //將二進位流反序列化為對象 using (MemoryStream outputStream = new MemoryStream(inputStream.ToArray())) { BinaryFormatter outputFormatter = new BinaryFormatter(); obj = outputFormatter.Deserialize(outputStream); } return obj; } } public class Fridge :Appliance { public Fridge() { type = "Fridge"; } public override void DoWork() { Console.WriteLine("do some fridge job"); } } public class Television:Appliance { public Television() { type = "Television"; } public override void DoWork() { Console.WriteLine("do some Television job"); } } }