設計模式和設計原則從程式設計開始就接觸了,但那個時候不知其所以然,工作一段時間後,再看設計模式,發現這東西在專案中或者框架中普遍存在。和以前的知識就融會貫通了。於是我打算自己寫一篇關於設計原則與設計模式博文吧。
為什麼要設計模式和設計原則呢?
- 提高程式碼質量和可維護性:設計模式和設計原則強調良好的軟體設計原則和實踐,例如高內聚、低耦合、單一職責原則等。通過遵循這些原則,可以編寫結構清晰、易於理解和維護的程式碼。
- 促程序式碼重用:設計模式鼓勵將可重用的元件和模組進行抽象和封裝,使其可以在不同的上下文中重複使用。這樣可以減少重複編寫程式碼的工作量,提高開發效率
- 增加程式碼的可延伸性和靈活性:設計模式和設計原則提供了一種靈活的架構和設計方法,使系統能夠輕鬆地擴充套件和適應變化。通過遵循開閉原則、依賴倒置原則等設計原則,可以使系統更容易進行功能擴充套件和修改。
- 促進團隊合作和交流:設計模式提供了一種共用的設計詞彙和概念,使團隊成員能夠更容易地理解和溝通設計決策。它們提供了一種通用的語言,促進了團隊合作和程式碼共用。
總的來說,設計模式和設計原則是經過驗證和廣泛應用的最佳實踐和經驗總結。它們幫助開發人員構建高質量的軟體系統,並提供瞭解決常見設計問題的方法。通過應用這些原則和模式,可以改善軟體的可維護性、可延伸性和可重用性,提高開發效率,並減少程式碼錯誤和重構的需求。
一個類只做一件事
class Animal{ void run(string name){ console.write(name+"能跑") } } var animal = new Animal() animal.run("狗") animal.run("小鳥") // 小鳥不能跑 /* 可以看到Animal類是單一原則的,只做一件事 方法之前也是單一原則的,當我們傳入小鳥就出現了問題 我們可以新增一個方法,這樣可以保證方式是單一原則,一個方法也做一件事,以後修改互不影響 */
就是面向介面程式設計,細節依賴抽象,抽象不依賴細節
例子:有一個食物類,我們應該把它抽象出來,讓具體的食物去實現食物介面,比如香蕉啊,蘋果啊,白米飯啊。這時假如有一個人要進食,只需要傳入食物介面,就可以了。
var people = new People(); people.eat(new Banana()); people.eat(new Apple()); // 食物介面 interface IFood { // 味道 string name{ get; set; } } // 香蕉 class Banana : IFood { public string name { get; set; } } // 蘋果 class Apple : IFood { public string name { get; set; } } // 人 class People { public void eat(IFood food) { Console.WriteLine("我要吃"+ food.name); } }
對擴充套件開放,對修改閉合
例子:有一個餵食的類,餵食的類關聯兩個物件,一個食物 一個是動物,食物應該是抽象的,動物應該也是抽象的,這樣我們以後要新增新的物件時,只需要實現對應的介面就行了,餵食類照樣工作
var feed = new Feed(); var dogFood = new DogFood(){value = "一號狗糧"}; var tigerFood = new DogFood(){value = "一號肉食"}; var dog = new List<Dog>() { new Dog(), new Dog() }; var tiger = new List<Tiger>() { new Tiger(), new Tiger() }; feed.StartFeed(dog, dogFood); feed.StartFeed(tiger, tigerFood); // 能吃東西的實現這個介面 interface IEat { void eat(IFoot foot); } // 食物實現這個介面 interface IFoot { string value { get; set; } } // 狗是動物 class Dog : IEat { public void eat(IFoot foot) { Console.WriteLine("狗吃"+foot.value); } } // 老虎是動物 class Tiger : IEat { public void eat(IFoot foot) { Console.WriteLine("老虎吃"+foot.value); } } // 狗吃的食物 class DogFood : IFoot { public string value { get; set; } } class TigerFood : IFoot { public string value { get; set; } } // 餵食類 class Feed { public void StartFeed(IEnumerable<IEat> eats,IFoot foot) { foreach (IEat eat in eats) { eat.eat(foot); } } }
父類別出現的地方,能用子類代替
interface IFood{ string name {get;set;} } class Banana:IFood{ string name {get;set;} } class Apple:IFood{ string name {get;set;} } IFood food1 = new Banana(); IFood food2 = new Apple();
不要依賴不需要的介面,介面不要設計的太過龐大
public void StartFeed(IEnumerable<IEat> eats,IFoot foot) { foreach (IEat eat in eats) { eat.eat(foot); } } /* 可以看到上面是滿足最小介面的, 如果IEat換成 IAnimal呢,就可能出現問題, 吃這個行為只能動物進行嗎?比如機器人吃電池呢 所以說,介面不要設計的太龐大,應該合理進行細分 */
一個模組對另一個模組應該要有儘可能少的瞭解,當要修改一個模組的時候影響的模組就小,使其功能獨立。
例子:有A和B物件,B裡面依賴了A,B在別的地方使用,B應該隱藏A
class A{ void say(){ console.write('aaa') } } class B{ // 這裡使用禁止public private A _A; public B(){ this._A = new A() } public say(){ // 我覺得這裡是迪米特法則的核心 this._B.say() } } class client{ void main{ B b = new B(); b.say() } }
全域性只有一個範例
class Example { private static Example _Example; static Example() { _Example = new Example(); Console.WriteLine("構造出來了哦"); } public static Example GetExample() { return _Example; } }
建立一個工廠介面,由子類去實現具體工廠的建立。工廠建立的物件稱其為產品。有了產品,當然要有建立產品介面。
例子
IShapeFactory shapeFactory = new CircleFactory(); // 或者 IShapeFactory shapeFactory = new RectangleFactory(); IShape shape = shapeFactory.CreateShape(); shape.draw();// 我是圓 /// <summary> /// 圖型介面 /// </summary> interface IShape { void draw(); } /// <summary> /// 圓形類 /// </summary> class Circle : IShape { public void draw() { Console.WriteLine("我是一個圓"); } } /// <summary> /// 矩形類 /// </summary> class Rectangle : IShape { public void draw() { Console.WriteLine("我是一個矩形"); } } /// <summary> /// 圖型工廠 /// </summary> interface IShapeFactory { IShape CreateShape(); } /// <summary> /// 生成圓形的工廠 /// </summary> class CircleFactory : IShapeFactory { public IShape CreateShape() { return new Circle(); } } /// <summary> /// 生成矩形的工廠 /// </summary> class RectangleFactory : IShapeFactory { public IShape CreateShape() { return new Rectangle(); } }
抽象工廠和工廠方法類似,只不過抽象工廠是一群工廠
範例
IGUIFactory factory = new CircleFactory(); // 這裡替換後,可以生成別的產品, IColor color1 = factory.createColor(); IText text1 = factory.createText(); color1.render(); text1.render(); /// <summary> /// 顏色介面 /// </summary> interface IColor { void render(); } /// <summary> /// 文字介面 /// </summary> interface IText { void render(); } /// <summary> /// 帶顏色的圓 /// </summary class CircleColor : IColor { public void render() { Console.WriteLine("我是一個帶顏色的圓"); } } /// <summary> /// 帶文字的圓 /// </summary> class CircleText : IText { public void render() { Console.WriteLine("我是一個帶文字的圓"); } } /// <summary> /// 帶顏色的圓 /// </summary class RectangleColor : IColor { public void render() { Console.WriteLine("我是一個帶顏色的矩形"); } } /// <summary> /// 帶文字的圓 /// </summary> class RectangleText : IText { public void render() { Console.WriteLine("我是一個帶文字的矩形"); } } /// <summary> /// 圖型工廠 /// </summary> interface IGUIFactory { IColor createColor(); IText createText(); } /// <summary> /// 生成圓形的工廠 /// </summary> class CircleFactory : IGUIFactory { public IColor createColor() { return new CircleColor(); } public IText createText() { return new CircleText(); } } /// <summary> /// 生成矩形的工廠 /// </summary> class RectangleFactory : IGUIFactory { public IColor createColor() { return new RectangleColor(); } public IText createText() { return new RectangleText(); } }
將物件構建的過程和細節分離,如下
// 指導者,用來指導構建的類 AppleDirector appleDirector = new AppleDirector(); // 構造一個Q蘋果 AppleBuild build = new QAppleBuild(); appleDirector.SetAppleBuild(build); Apple apple = appleDirector.Build(); apple.display(); /// <summary> /// 蘋果類 /// </summary> class Apple { public string name { get; set; } public string color { get; set; } public void display() { Console.WriteLine(name); Console.WriteLine(color); } } /// <summary> /// 抽象建造者 /// </summary> abstract class AppleBuild{ protected Apple _apple; public abstract void nameBuilder(); public abstract void colorBuilder(); public AppleBuild() { _apple = new Apple(); } public Apple getApple() { return _apple; } } class QAppleBuild : AppleBuild { public override void colorBuilder() { base._apple.color = "綠色"; } public override void nameBuilder() { base._apple.name = "綠蘋果"; } } class WAppleBuild : AppleBuild { public override void colorBuilder() { base._apple.color = "紅色"; } public override void nameBuilder() { base._apple.name = "紅蘋果"; } } /// <summary> /// 蘋果的指導者 /// </summary> class AppleDirector { private AppleBuild _appleBuild; public void SetAppleBuild(AppleBuild appleBuild) { _appleBuild = appleBuild; } public Apple Build() { this._appleBuild.colorBuilder(); this._appleBuild.nameBuilder(); return this._appleBuild.getApple(); } }
原型工廠模式通過克隆現有物件來建立新物件
ShapeFactory factory = new ShapeFactory(); factory.GetShape(nameof(Circle)).draw(); factory.GetShape(nameof(Rectangle)).draw(); abstract class Shape { public abstract void draw(); public abstract Shape clone(); } class Circle : Shape { public override Shape clone() { return new Circle(); } public override void draw() { Console.WriteLine("我是一個圓"); } } class Rectangle : Shape { public override Shape clone() { return new Rectangle(); } public override void draw() { Console.WriteLine("我是一個矩形"); } } class ShapeFactory { private Dictionary<string, Shape> shapeCache; public ShapeFactory() { shapeCache = new Dictionary<string, Shape>(); shapeCache.Add(nameof(Circle), new Circle()); shapeCache.Add(nameof(Rectangle), new Rectangle()); } public Shape GetShape(string type) { if (shapeCache.ContainsKey(type)) { return shapeCache[type].clone(); } return null; } }
介面卡模式意在轉換介面,它能夠使原本不能再一起工作的兩個類一起工作,所以經常用來在類庫的複用
IPlay play = new VideoAdapter(new Video()); interface IPlay { void show(); } class Video { public void play() { Console.WriteLine("輸出視訊"); } } /// <summary> /// 介面卡,適配給IPlay使用 /// </summary> class VideoAdapter : IPlay { private Video video; public VideoAdapter(Video video) { this.video = video; } public void show() { video.play(); } }
將抽象和實現進行分離,兩者可以獨立地變化
//IShape shape = new Rectangle(new RedColor()); 具體的形狀和顏色可以任意變換,業務不受影響 IShape shape = new Rectangle(new BlueColor()); shape.draw(); /// <summary> /// 形狀類 /// </summary> interface IShape { void draw(); } class Circle : IShape { private IColor color; public Circle(IColor color) { this.color = color; } public void draw() { Console.WriteLine("我是圓形"); this.color.fill(); } } class Rectangle : IShape { private IColor color; public Rectangle(IColor color) { this.color = color; } public void draw() { Console.WriteLine("我是矩形"); this.color.fill(); } } /// <summary> /// 顏色類 /// </summary> interface IColor { void fill(); } /// <summary> /// 紅色 /// </summary> class RedColor : IColor { public void fill() { Console.WriteLine("紅色"); } } /// <summary> /// 藍色 /// </summary> class BlueColor : IColor { public void fill() { Console.WriteLine("藍色"); } }
在物件新增新東西,不修改原來物件
// 普通咖啡 ICoffee coffee = new Coffee(); Console.WriteLine(coffee.GetDescription()); // 裝飾器裝飾 coffee = new QCoffee(coffee); Console.WriteLine(coffee.GetDescription()); coffee = new WCoffee(coffee); Console.WriteLine(coffee.GetDescription()); /// <summary> /// 咖啡介面 /// </summary> interface ICoffee { string GetDescription(); double GetCost(); } class Coffee : ICoffee { public double GetCost() { return 2; } public string GetDescription() { return "咖啡"; } } /// <summary> /// 裝飾器基礎類別 /// </summary> abstract class CoffeeDecorato : ICoffee { private ICoffee coffee; public CoffeeDecorato(ICoffee coffee) { this.coffee = coffee; } public virtual double GetCost() { return coffee.GetCost(); } public virtual string GetDescription() { return coffee.GetDescription(); } } class QCoffee : CoffeeDecorato { public QCoffee(ICoffee coffee) : base(coffee) { } public override string GetDescription() { return base.GetDescription()+"q咖啡,得價錢10塊"; } public override double GetCost() { return base.GetCost()+10; } } class WCoffee : CoffeeDecorato { public WCoffee(ICoffee coffee) : base(coffee){} public override string GetDescription() { return base.GetDescription() + "w咖啡,得價錢20塊"; } public override double GetCost() { return base.GetCost() + 20; } }
組合模式將物件組合成樹形結構,用來表示整體與部分的關係
File file1 = new File("檔案1"); File file2 = new File("檔案2"); Folder folder1 = new Folder("資料夾1"); Folder folder2 = new Folder("資料夾2"); folder1.add(file1); folder2.add(file2); folder2.add(folder1); /// <summary> /// 抽象公共屬性 /// </summary> abstract class IFolderCommon { public IFolderCommon(string name) { this.name = name; } public string name { get; set; } } /// <summary> /// 檔案 /// </summary> class File : IFolderCommon { public File(string name): base(name){} } /// <summary> /// 資料夾 /// </summary> class Folder : IFolderCommon { public List<IFolderCommon> _folder; public Folder(string name) : base(name) { this._folder = new List<IFolderCommon>(); } public void add(IFolderCommon folder) { this._folder.Add(folder); } public void remove(IFolderCommon folder) { this._folder.Remove(folder); } }
使用者端不與子系統互動, 提供簡化的介面,降低使用者端與複雜系統的互動
/// <summary> /// 庫存管理 /// </summary> class InventorySystem{ // 檢查庫存是否足夠 public bool CheckStock(string id) { return false; } } /// <summary> /// 訂單管理 /// </summary> class OrderSystem { // 建立訂單 public string CreateOrder() { return "訂單號"; } } /// <summary> /// 電子商務外觀 /// </summary> class ECommercePlatformFacade { private InventorySystem _inventorySystem; private OrderSystem _orderSystem; public ECommercePlatformFacade() { _inventorySystem = new InventorySystem(); _orderSystem = new OrderSystem(); } // 使用者下單 public void PlaceOrder(List<string> ids) { foreach (string id in ids) { // 檢查庫存是否足夠 if (_inventorySystem.CheckStock(id)) { // 建立訂單 _orderSystem.CreateOrder(); } } } } /// <summary> /// 使用者端 /// </summary> class Client { public void main() { ECommercePlatformFacade platformFacade = new ECommercePlatformFacade(); // 使用者批次下單 platformFacade.PlaceOrder(new List<string>() { "1", "2" }); } }
將類似的物件快取起來,以後重複使用,避免new開銷,注意物件釋放時機!
/// <summary> /// 享元介面 /// </summary> public interface IPlayer { void AssignWeapon(string weapon); void Play(); } /// <summary> /// 實現類 /// </summary> public class Player : IPlayer { private string weapon; public void AssignWeapon(string weapon) { this.weapon = weapon; } public void Play() { Console.WriteLine(weapon); } } /// <summary> /// 享元工廠 /// </summary> public class PlayerFactory { /// <summary> /// 快取起來,享元 /// </summary> private Dictionary<string,IPlayer> players; public PlayerFactory() { this.players = new Dictionary<string,IPlayer>(); } public IPlayer GetPlayer(string weapon) { if (players.ContainsKey(weapon)) { return players[weapon]; } else { IPlayer player = new Player(); player.AssignWeapon(weapon); players.Add(weapon, player); return player; } } }
通過代理的方式,間接的存取物件
// 統一介面 public interface ISubject { void Request(); } // 實現類 public class RealSubject : ISubject { public void Request() { Console.WriteLine("come"); } } // 代理類 public class Proxy: ISubject { private RealSubject realSubject; public void Request() { if (realSubject == null) { realSubject = new RealSubject(); } // 這裡進行代理 realSubject.Request(); } } // 使用者端 public class Client { public void main() { Proxy proxy = new Proxy(); proxy.Request(); } }
提供一套模板,走特定的程式,然後讓子類去繼承它,重寫一些通用的邏輯
Template temp = new TimeTask(); temp.run(); // 模板類 abstract class Template { public void run() { // 走特定的流程 Start(); Add(); End(); } protected void Start() { Console.WriteLine("任務開"); } /// <summary> /// 提供一個模板 /// </summary> protected abstract void Add(); protected void End() { Console.WriteLine("任務結束"); } } // 實現類 class TimeTask : Template { protected override void Add() { Console.WriteLine("中間插入的內容"); } } // 使用者端 class Client { void main() { Template temp = new TimeTask(); temp.run(); } }
定義命令介面,實現具體的命令,然後呼叫者,接收一個命令介面,使用者端傳入具體命令
// 命令介面 interface ICommand { void Execute(); } // 命令實現類 class OpenDocument: ICommand { private Document doc; public OpenDocument(Document doc) { this.doc = doc; } public void Execute() { this.doc.Open(); } } // 命令實現類 class CloseDocument : ICommand { private Document doc; public CloseDocument(Document doc) { this.doc = doc; } public void Execute() { this.doc.Close(); } } // 檔案類 class Document { public void Open() { } public void Close() { } } // 使用者端使用 class Button { private ICommand cmd; public void SetCommand(ICommand cmd) { this.cmd = cmd; } public void Click() { // 寫具體的業務 cmd.Execute(); } } class Client { void main() { Document doc = new Document(); ICommand cmd = new OpenDocument(doc); Button btn = new Button(); btn.SetCommand(cmd); btn.Click(); // 開啟 } }
迭代器模式,針對集合物件,將其封裝成可遍歷
// 迭代器介面 public interface IIterator<T> { bool hasNext(); T next(); } // 集合介面 public interface ICollection<T> { IIterator<T> CreateIterator(); } // 集合類的實現 public class MyCollection<T> : ICollection<T> { private List<T> items; public MyCollection() { items = new List<T>();// 初始化集合 } public void Add(T data) { items.Add(data); } // 轉換成可迭代物件 public IIterator<T> CreateIterator() { return new MyIterator<T>(items); } } // 迭代器的實現 public class MyIterator<T> : IIterator<T> { private List<T> items; private int currentIndex; public MyIterator(List<T> items) { this.items = items; this.currentIndex = 0; } public bool hasNext() { return currentIndex < items.Count; } public T next() { T data = items[currentIndex]; currentIndex++; return data; } } class Client { void main() { MyCollection<string> arr = new MyCollection<string>(); arr.Add("a"); arr.Add("b"); arr.Add("c"); var iarr = arr.CreateIterator(); while (iarr.hasNext()) { Console.WriteLine(iarr.next() + "---"); } } }
一對多關係,當一個物件的狀態發生了變化,其相關的依賴物件都能夠得到通知
// 主題介面 public interface ISubject { void Attach(IObserver observer); void Detach(IObserver observer); void Notify(); } // 觀察者介面 public interface IObserver { void Update(); } // 主題實現類 public class Subject : ISubject { List<IObserver> observers = new List<IObserver>(); public void Attach(IObserver observer) { observers.Add(observer); } public void Detach(IObserver observer) { observers.Remove(observer); } // 通知所有觀察者 public void Notify() { foreach (var item in observers) { item.Update(); } } public void SetTime() { Console.WriteLine("主題設定了時間"); this.Notify(); } } // 觀察者實現類 public class Observer : IObserver { public void Update() { Console.WriteLine("+"); } } // 使用者端 class Client { void main() { Observer observer1 = new Observer(); Observer observer2 = new Observer(); Subject subject = new Subject(); subject.Attach(observer1); subject.Attach(observer2); subject.SetTime(); // 會自動通知觀察者 } }
物件之間不直接通訊,而是通過中介者物件來進行通訊
// 中介者介面 public interface IChatRoom { void SendMessage(User user,string msg); } // 中介者實現類 public class ChatRoom : IChatRoom { List<User> users; public ChatRoom() { users = new List<User>(); } public void SendMessage(User user, string msg) { foreach (var item in users) { if (item != user) { item.ReciveMessage(msg); } } } public void Add(User user) { users.Add(user); } } // 使用者類 public class User { public string Name { get; set; } public IChatRoom ChatRoom { get; set; } public User(IChatRoom chatRoom,string Name) { this.Name = Name; this.ChatRoom = chatRoom; } public void SendMessage(string msg) { // 重點!!,通過中介者進行使用者互動 ChatRoom.SendMessage(this, msg); } public void ReciveMessage(string msg) { Console.WriteLine("接受到訊息:"+msg); } } class Client { void main() { ChatRoom room = new ChatRoom(); User user1 = new User(room, "張三"); User user2 = new User(room, "李四"); User user3 = new User(room, "王五"); room.Add(user1); room.Add(user2); room.Add(user3); user1.SendMessage("天氣不錯"); } }
將狀態封裝成獨立的一個類, 通過修改一個類的狀態,以實現不同的邏輯
// 編輯器狀態介面 public interface IEditorState { void Edit(); void Save(); } /// <summary> /// 編輯狀態 /// </summary> public class EditEditorState : IEditorState { public void Edit() { Console.WriteLine("編輯"); } public void Save() { Console.WriteLine("編輯狀態 無法儲存"); } } // 預覽狀態 public class ViewEditorState : IEditorState { public void Edit() { Console.WriteLine("預覽狀態 無法修改"); } public void Save() { Console.WriteLine("儲存"); } } // 編輯器實現類 public class EditorState : IEditorState { public IEditorState EditState { get; set; } // 重點 此方法更改狀態,以實現不同邏輯 public EditorState() { this.EditState = new EditEditorState(); } public void SetState(IEditorState EditState) { this.EditState = EditState; } public void Edit() { this.EditState.Edit(); } public void Save() { this.EditState.Save(); } } // 使用者端 class Client { void main() { EditorState editor = new EditorState(); editor.Edit(); editor.Save(); // 這裡切換狀態 editor.SetState(new ViewEditorState()); editor.Edit(); editor.Save(); } }
將一個類的具體演演算法,抽離出來成為策略,切換策略可以實現不同的業務
// 策略介面 public interface IDrawingStrategy { void Draw(); } // 實線策略 public class SolidLineDrawingStrategy : IDrawingStrategy { public void Draw() { Console.WriteLine("繪製實線"); } } // 虛線策略 public class DottedLineDrawingStrategy : IDrawingStrategy { public void Draw() { Console.WriteLine("繪製虛線"); } } // 繪製策略上下文 public class DrawingContext { private IDrawingStrategy drawingStrategy; public void SetDrawingStrategy(IDrawingStrategy drawingStrategy) { this.drawingStrategy = drawingStrategy; } // 繪製 public void Draw() { drawingStrategy.Draw(); } } // 使用者端 class Client { void main() { DrawingContext drawing = new DrawingContext(); drawing.SetDrawingStrategy(new SolidLineDrawingStrategy()); // 更改策略 drawing.Draw(); drawing.SetDrawingStrategy(new DottedLineDrawingStrategy()); // 更改策略 drawing.Draw(); } }
沿著處理鏈傳遞,直到有一個能處理為止
// 抽象責任鏈 public abstract class Handler { protected Handler success; public void SetHandle(Handler success) { this.success = success; } public abstract void Request(int sum); } public class A : Handler { public override void Request(int sum) { if(sum>=0 && sum <= 10) { Console.WriteLine("進入a"); }else if (success != null) { // 傳遞給下一個 success.Request(sum); } } } public class B : Handler { public override void Request(int sum) { if (sum >10 && sum <= 20) { Console.WriteLine("進入b"); } else if (success != null) { // 傳遞給下一個 success.Request(sum); } } } public class C : Handler { public override void Request(int sum) { if (sum > 20 && sum <= 30) { Console.WriteLine("進入c"); } else if (success != null) { // 傳遞給下一個 success.Request(sum); } } } // 使用者端 class Client { void main() { A a = new A(); B b = new B(); C c = new C(); a.SetHandle(b); b.SetHandle(c); a.Request(15); } }
在不改變物件的結構,定義新的操作。元素裡面有一個方法來接受存取者,如此以後需要新的操作,只需要新增存取者類即可
ObjectStructure obj = new ObjectStructure(); ElementA a = new ElementA(); ElementB b = new ElementB(); VisitorA va = new VisitorA(); VisitorB vb = new VisitorB(); obj.Add(a); obj.Add(b); obj.show(va); obj.show(vb); // 存取者介面 public interface IVisitor { void Visitor(IElement el); } // 具體存取者A public class VisitorA : IVisitor { public void Visitor(IElement el) { Console.WriteLine("存取者A進行存取"); } } // 具體存取者B public class VisitorB : IVisitor { public void Visitor(IElement el) { Console.WriteLine("存取者B進行存取"); } } // 元素抽象類 public abstract class IElement { public abstract void Accept(IVisitor visitor); } // 具體元素類A public class ElementA : IElement { public override void Accept(IVisitor visitor) { visitor.Visitor(this); } } // 具體元素類B public class ElementB: IElement { public override void Accept(IVisitor visitor) { visitor.Visitor(this); } } // 定義一個結構 public class ObjectStructure{ List<IElement> children; public ObjectStructure() { children = new List<IElement>(); } public void Add(IElement element) { this.children.Add(element); } // 重點!,這裡將存取者傳遞進來,存取者執行裡面的邏輯 public void show(IVisitor visitor) { foreach (var item in children) { item.Accept(visitor); } } }
捕獲和恢復物件的狀態,同時保持物件的封裝性,對於實現復原,恢復或歷史記錄功能的應用程式非常有用
// 備忘錄 public class MemoInfo { public string State { get; } public MemoInfo(string state) { this.State = state; } } // 操作物件 public class OriginMemo { public string state; public string State { get { return this.state; } set { this.state = value; Console.WriteLine("設定成:"+this.state); } } public MemoInfo CreateMemoInfo() { return new MemoInfo(State); } public void RestData(MemoInfo memoInfo) { this.state = memoInfo.State; Console.WriteLine("恢復成:"+this.state); } } // 管理類 public class ManagerMemo { public MemoInfo Memo { get; set; } } class Client { void main() { OriginMemo memo = new OriginMemo(); memo.State = "狀態1"; ManagerMemo manager = new ManagerMemo(); manager.Memo = memo.CreateMemoInfo(); // 這裡保留原有物件 memo.State = "狀態2"; memo.RestData(manager.Memo); // 這裡進行恢復 } }
定義語言文法,並解釋該語言的表示式
// 表示式類 public interface IExpression { int Interpret(); } // 加法表示式類 public class AddExpression : IExpression { private readonly IExpression left; private readonly IExpression right; public AddExpression(IExpression left,IExpression right) { this.left = left; this.right = right; } public int Interpret() { return left.Interpret() + right.Interpret(); } } // 數位類 public class NumberExpression : IExpression { private int number; public NumberExpression(int number = 0) { this.number = number; } public int Interpret() { return number; } } // 使用者端 class Client { void main() { IExpression a1 = new NumberExpression(1); IExpression a2 = new NumberExpression(3); IExpression a3 = new AddExpression(a1, a2); Console.WriteLine(a3.Interpret()); } }
本文來自部落格園,作者:Pro成,轉載請註明原文連結:https://www.cnblogs.com/ProCheng/p/17509163.html