C#面試題(中級篇),詳細講解,幫助你深刻理解,拒絕背話術!-CSDN博客
簡單工廠模式
優點:
根據條件有工廠類直接創建具體的產品
客戶端無需知道具體的對象名字,可以通過配置文件創建,靈活。
缺點:
每增加一個對象,就需要在工廠添加新的產品,修改工廠邏輯,不易拓展
?
using System;// 定義產品的抽象基類
public abstract class Product
{public abstract void Use();
}// 具體產品類A
public class ConcreteProductA : Product
{public override void Use(){Console.WriteLine("Using ConcreteProductA");}
}// 具體產品類B
public class ConcreteProductB : Product
{public override void Use(){Console.WriteLine("Using ConcreteProductB");}
}// 簡單工廠類
public class SimpleFactory
{public static Product CreateProduct(string type){switch (type){case "A":return new ConcreteProductA();case "B":return new ConcreteProductB();default:throw new ArgumentException("Invalid product type");}}
}class Program
{static void Main(){Product productA = SimpleFactory.CreateProduct("A");productA.Use();Product productB = SimpleFactory.CreateProduct("B");productB.Use();}
}
工廠方法模式
解決了簡單工廠的 開放-關閉原則
不同的子類由工廠子類創建
但是對象數量會很多
抽象工廠
抽象工廠:(相當于有多個工廠)不同廠商生產的同一產品,產品擁有相同的結構,區別在于不同的廠商和動作的細節。比如多個電腦工廠,生產不同品牌的電腦,電腦有多個配件,每個工廠都生產這些配件()。
抽象工廠有產品,繼承的工廠生產對應廠商的產品。
using System;// 定義產品A的抽象基類
public abstract class AbstractProductA
{public abstract void UseA();
}// 具體產品A1
public class ConcreteProductA1 : AbstractProductA
{public override void UseA(){Console.WriteLine("Using ConcreteProductA1");}
}// 具體產品A2
public class ConcreteProductA2 : AbstractProductA
{public override void UseA(){Console.WriteLine("Using ConcreteProductA2");}
}// 定義產品B的抽象基類
public abstract class AbstractProductB
{public abstract void UseB();
}// 具體產品B1
public class ConcreteProductB1 : AbstractProductB
{public override void UseB(){Console.WriteLine("Using ConcreteProductB1");}
}// 具體產品B2
public class ConcreteProductB2 : AbstractProductB
{public override void UseB(){Console.WriteLine("Using ConcreteProductB2");}
}// 抽象工廠類
public abstract class AbstractFactory
{public abstract AbstractProductA CreateProductA();public abstract AbstractProductB CreateProductB();
}// 具體工廠類1,負責創建產品A1和產品B1
public class ConcreteFactory1 : AbstractFactory
{public override AbstractProductA CreateProductA(){return new ConcreteProductA1();}public override AbstractProductB CreateProductB(){return new ConcreteProductB1();}
}// 具體工廠類2,負責創建產品A2和產品B2
public class ConcreteFactory2 : AbstractFactory
{public override AbstractProductA CreateProductA(){return new ConcreteProductA2();}public override AbstractProductB CreateProductB(){return new ConcreteProductB2();}
}class Program
{static void Main(){AbstractFactory factory1 = new ConcreteFactory1();AbstractProductA productA1 = factory1.CreateProductA();AbstractProductB productB1 = factory1.CreateProductB();productA1.UseA();productB1.UseB();AbstractFactory factory2 = new ConcreteFactory2();AbstractProductA productA2 = factory2.CreateProductA();AbstractProductB productB2 = factory2.CreateProductB();productA2.UseA();productB2.UseB();}
}
觀察者模式(發布-訂閱)
和事件系統的邏輯基本一致
一個發布者,多個訂閱者。把觀察者注冊進去。下圖是簡易的事件系統
using System;
using System.Collections.Generic;// 定義觀察者接口
public interface IObserver
{void Update(string message);
}// 定義主題接口
public interface ISubject
{void RegisterObserver(IObserver observer);void RemoveObserver(IObserver observer);void NotifyObservers();
}// 具體主題類
public class ConcreteSubject : ISubject
{private List<IObserver> observers = new List<IObserver>();private string message;public void RegisterObserver(IObserver observer){observers.Add(observer);}public void RemoveObserver(IObserver observer){observers.Remove(observer);}public void NotifyObservers(){foreach (var observer in observers){observer.Update(message);}}public void SetMessage(string newMessage){message = newMessage;NotifyObservers();}
}// 具體觀察者類
public class ConcreteObserver : IObserver
{private string name;public ConcreteObserver(string name){this.name = name;}public void Update(string message){Console.WriteLine($"{name} received message: {message}");}
}class Program
{static void Main(){// 創建主題ConcreteSubject subject = new ConcreteSubject();// 創建觀察者ConcreteObserver observer1 = new ConcreteObserver("Observer 1");ConcreteObserver observer2 = new ConcreteObserver("Observer 2");// 注冊觀察者subject.RegisterObserver(observer1);subject.RegisterObserver(observer2);// 主題發布消息subject.SetMessage("New message from the subject!");// 移除一個觀察者subject.RemoveObserver(observer2);// 主題再次發布消息subject.SetMessage("Another message from the subject!");}
}
狀態模式
特點:
和FSM有限狀態機是相似邏輯,可以說FSM是狀態模式的運用
將狀態相關的行為封裝到不同的狀態類中,使得狀態的變化和對象行為的變化能夠獨立進行,符合開閉原則。
游戲中角色的不同狀態(如奔跑、跳躍、攻擊等)可用狀態模式實現,每個狀態有不同行為邏輯
using System;// 定義狀態接口
public interface IState
{void Handle(Context context);
}// 具體狀態類A
public class ConcreteStateA : IState
{public void Handle(Context context){Console.WriteLine("Handling state A. Transitioning to state B.");context.State = new ConcreteStateB();}
}// 具體狀態類B
public class ConcreteStateB : IState
{public void Handle(Context context){Console.WriteLine("Handling state B. Transitioning to state A.");context.State = new ConcreteStateA();}
}// 上下文類
public class Context
{private IState state;public Context(IState initialState){this.state = initialState;}public IState State{get { return state; }set{state = value;Console.WriteLine($"State changed to {state.GetType().Name}");}}public void Request(){state.Handle(this);}
}class Program
{static void Main(){// 創建初始狀態IState initialState = new ConcreteStateA();// 創建上下文對象Context context = new Context(initialState);// 執行請求,觸發狀態轉換context.Request();context.Request();}
}
IState
?接口:定義了狀態的行為方法?Handle
,具體的狀態類需要實現該方法。ConcreteStateA
?和?ConcreteStateB
?類:實現了?IState
?接口,分別代表不同的狀態,在?Handle
?方法中處理當前狀態的邏輯,并可以進行狀態的轉換。Context
?類:維護一個當前狀態的引用?state
,通過?Request
?方法調用當前狀態的?Handle
?方法,同時提供了?State
?屬性用于改變當前狀態。
優點
- 可維護性高:將不同狀態的行為封裝到不同的狀態類中,使得代碼結構清晰,易于理解和維護。當需要添加新的狀態時,只需要創建一個新的狀態類并實現相應的行為,而不需要修改現有的代碼。
- 可擴展性強:符合開閉原則,對擴展開放,對修改關閉。可以方便地添加新的狀態和狀態轉換邏輯,而不會影響其他狀態類和上下文類。
- 狀態轉換清晰:狀態的轉換邏輯集中在狀態類中,使得狀態轉換的規則更加清晰,易于管理和調試。
缺點
- 類的數量增加:每個狀態都需要一個對應的狀態類,當狀態較多時,會導致類的數量增加,增加了系統的復雜性。
- 狀態之間的耦合:狀態類之間可能存在一定的耦合,特別是在狀態轉換時,一個狀態類可能需要知道其他狀態類的信息,這可能會影響代碼的可維護性。
?裝飾器模式
動態地給對象添加額外職責。游戲中給角色添加裝備或增益效果可使用裝飾器模式
?
using System;// 定義組件接口
public interface IComponent
{void Operation();
}// 具體組件類
public class ConcreteComponent : IComponent
{public void Operation(){Console.WriteLine("ConcreteComponent: Performing basic operation.");}
}// 裝飾器抽象類
public abstract class Decorator : IComponent
{protected IComponent component;public Decorator(IComponent component){this.component = component;}public virtual void Operation(){if (component != null){component.Operation();}}
}// 具體裝飾器類A
public class ConcreteDecoratorA : Decorator
{public ConcreteDecoratorA(IComponent component) : base(component){}public override void Operation(){base.Operation();AddedBehaviorA();}private void AddedBehaviorA(){Console.WriteLine("ConcreteDecoratorA: Adding additional behavior A.");}
}// 具體裝飾器類B
public class ConcreteDecoratorB : Decorator
{public ConcreteDecoratorB(IComponent component) : base(component){}public override void Operation(){base.Operation();AddedBehaviorB();}private void AddedBehaviorB(){Console.WriteLine("ConcreteDecoratorB: Adding additional behavior B.");}
}class Program
{static void Main(){// 創建具體組件IComponent component = new ConcreteComponent();// 使用具體裝飾器A包裝組件IComponent decoratedComponentA = new ConcreteDecoratorA(component);// 使用具體裝飾器B包裝經過裝飾器A包裝的組件IComponent decoratedComponentB = new ConcreteDecoratorB(decoratedComponentA);// 調用操作方法decoratedComponentB.Operation();}
}
優點:
-
裝飾類和被裝飾類可以獨立發展,不會相互耦合。
-
裝飾模式是繼承的一個替代模式,裝飾模式可以動態擴展一個實現類的功能。
缺點:
-
多層裝飾比較復雜。
適配器模式
將一個類的接口轉換成客戶希望的另一個接口。適配器模式主要有類適配器模式和對象適配器模式兩種實現方式。
對象適配器:相當于把對象作為一個屬性
類適配器:相當于繼承
對象:
using System;// 目標接口,客戶端所期望的接口
public interface ITarget
{void Request();
}// 適配者類,需要被適配的類
public class Adaptee
{public void SpecificRequest(){Console.WriteLine("Adaptee: Specific request.");}
}// 適配器類,實現目標接口并持有適配者對象
public class Adapter : ITarget
{private Adaptee adaptee;public Adapter(Adaptee adaptee){this.adaptee = adaptee;}public void Request(){adaptee.SpecificRequest();}
}class Program
{static void Main(){// 創建適配者對象Adaptee adaptee = new Adaptee();// 創建適配器對象并傳入適配者對象ITarget adapter = new Adapter(adaptee);// 通過適配器調用目標接口方法adapter.Request();}
}
類:
using System;// 目標接口
public interface ITargetClassAdapter
{void Request();
}// 適配者類
public class AdapteeClassAdapter
{public void SpecificRequest(){Console.WriteLine("AdapteeClassAdapter: Specific request.");}
}// 適配器類,繼承適配者類并實現目標接口
public class ClassAdapter : AdapteeClassAdapter, ITargetClassAdapter
{public void Request(){SpecificRequest();}
}class ProgramClassAdapter
{static void Main(){// 創建類適配器對象ITargetClassAdapter adapter = new ClassAdapter();// 通過適配器調用目標接口方法adapter.Request();}
}
優點
-
提高復用性:可以讓原本不兼容的類一起工作,使得一些已經存在的類可以被復用,無需對其進行修改。例如,當你有一個舊的庫,其接口與新系統不兼容時,使用適配器模式可以將其集成到新系統中。
-
靈活性和擴展性:適配器模式符合開閉原則,當需要適配新的類時,只需要創建新的適配器類,而不需要修改現有的代碼。
-
解耦性:將客戶端和適配者解耦,客戶端只需要與目標接口交互,而不需要關心適配者的具體實現。
缺點
-
增加系統復雜度:引入適配器類會增加系統的類數量和代碼復雜度,特別是當存在多個適配器時,可能會使系統變得難以理解和維護。
-
過多使用會導致代碼混亂:如果過度使用適配器模式,可能會導致系統中存在大量的適配器類,使得代碼結構變得混亂,難以把握整體的設計意圖。