文章目錄
- 設計模型概念
- 單例模式
- 工廠模式
- 策略模式
- 責任鏈模式
設計模型概念
設計模式是前人總結的軟件設計經驗和解決問題的最佳方案,它們為我們提供了一套可復用、易維護、可擴展的設計思路。
(1)定義: 設計模式是一套經過驗證的解決特定設計問題的模板,這些模板并不是代碼,而是對類、對象以及它們之間如何協作的抽象描述。
(2)目的: 降低系統的耦合性、提高代碼的復用性和可維護性,以及應對不斷變化的需求。
(3)設計模式主要可以分為三大類:創建型、結構型和行為型。以下是一些在 JAVA 開發工程師面試中常見的設計模式:
1. 創建型模式
- 單例模式(Singleton Pattern)
- 定義: 確保一個類只有一個實例,并提供一個全局訪問點。
- 使用場景: 當系統中需要唯一一個對象來協調各部分工作,如配置管理、線程池、日志對象等。
- 工廠模式(Factory Pattern)
- 定義: 定義一個用于創建對象的接口,由子類決定實例化哪一個類。
- 使用場景: 當系統中有大量對象創建需求,且對象之間具有共同接口或父類時,可以使用工廠模式封裝對象的創建邏輯,降低耦合。
- 建造者模式(Builder Pattern)
- 定義: 將一個復雜對象的構建過程與它的表示分離,使得同樣的構建過程可以創建不同的表示。
- 使用場景: 當一個對象的構造過程復雜,涉及多個步驟或多個可選參數時,使用建造者模式能讓代碼更清晰、更易擴展。
2. 結構型模式
- 適配器模式(Adapter Pattern)
- 定義: 將一個類的接口轉換成客戶期望的另一個接口,使得原本因接口不兼容而不能一起工作的類可以協同工作。
- 使用場景: 當你想要使用一些現有的類,但它們的接口與當前系統不匹配時,可以使用適配器模式。
- 裝飾器模式(Decorator Pattern)
- 定義: 動態地給一個對象添加一些額外的職責,而不影響其他對象。
- 使用場景: 當系統需要在不改變原有對象結構的情況下增加功能時,裝飾器模式提供了一種靈活的解決方案。
- 外觀模式(Facade Pattern)
- 定義: 為復雜的子系統提供一個簡單的接口,使得客戶端可以更容易地使用子系統。
- 使用場景: 當系統中存在多個相互依賴的類或接口時,通過外觀模式可以將復雜性隱藏起來,提供一個統一的接口。
3. 行為型模式
- 觀察者模式(Observer Pattern)
- 定義: 定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,其相關依賴對象會收到通知并自動更新。
- 使用場景: 當一個對象狀態的變化需要通知其他對象,且不知道這些對象的數量或具體類型時,可以使用觀察者模式,如事件監聽機制。
- 策略模式(Strategy Pattern)
- 定義: 定義一系列算法,把它們一個個封裝起來,并使它們可以互換。
- 使用場景: 當系統中存在多種算法或行為,并且需要根據具體情況選擇不同的算法時,策略模式能使算法切換更為靈活。
- 模板方法模式(Template Method Pattern)
- 定義: 在一個方法中定義一個算法的骨架,將某些步驟延遲到子類中實現,從而使子類可以不改變算法結構的情況下重新定義算法的某些步驟。
- 使用場景: 當多個子類有很多相同的行為,只在細節上略有不同的情況下,模板方法模式可以復用公共代碼,同時讓子類實現具體差異部分。
- 代理模式(Proxy Pattern)
- 定義: 為其他對象提供一種代理以控制對這個對象的訪問。
- 使用場景: 當你需要在訪問對象時附加一些額外操作(如懶加載、安全控制、緩存等)時,可以使用代理模式來控制對象的訪問。
單例模式
確保一個類只有一個實例,并提供一個全局訪問點。
Spring 框架中,默認 bean
的作用域為單例(singleton),即在整個應用上下文中只存在一個實例。
如 Spring 的 ApplicationContext
在加載 bean 時會確保同一個 bean 只被實例化一次(除非配置為其他作用域)。
public class Singleton {// 餓漢式單例private static volatile Singleton instance = null;// 私有構造方法,防止外部實例化private Singleton() {}public static Singleton getInstance() {if (instance == null) {sychronized(Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}
工廠模式
定義一個用于創建對象的接口,由子類決定實例化哪一個類。
Spring 的 BeanFactory
或 ApplicationContext
實際上就是一個工廠,通過配置文件或注解來實例化并管理對象。
FactoryBean
接口允許開發者自定義 bean
的創建邏輯。
// 定義產品接口
public interface Product {void use();
}// 具體產品A
public class ConcreteProductA implements Product {@Overridepublic void use() {System.out.println("使用產品A");}
}// 具體產品B
public class ConcreteProductB implements Product {@Overridepublic void use() {System.out.println("使用產品B");}
}// 工廠類
public class ProductFactory {public static Product createProduct(String type) {if ("A".equals(type)) {return new ConcreteProductA();} else if ("B".equals(type)) {return new ConcreteProductB();}throw new IllegalArgumentException("未知產品類型:" + type);}
}// 測試入口
public class FactoryDemo {public static void main(String[] args) {Product productA = ProductFactory.createProduct("A");productA.use();Product productB = ProductFactory.createProduct("B");productB.use();}
}
策略模式
定義一系列算法,把它們一個個封裝起來,并使它們可以互換。
當系統中有多種算法或行為需要在運行時動態切換時,可以使用策略模式。
Spring MVC 中,通過 HandlerAdapter
接口支持多種類型的控制器(如 @Controller
、@RestController
等),根據實際請求選擇合適的適配器來處理業務邏輯。
事務管理、緩存策略等也采用了類似思想,通過接口和多種實現來動態選擇行為。
// 策略接口
public interface Strategy {void execute();
}// 具體策略A
public class ConcreteStrategyA implements Strategy {@Overridepublic void execute() {System.out.println("執行策略A");}
}// 具體策略B
public class ConcreteStrategyB implements Strategy {@Overridepublic void execute() {System.out.println("執行策略B");}
}// 上下文,使用策略
public class Context {private Strategy strategy;public Context(Strategy strategy) {this.strategy = strategy;}public void executeStrategy() {strategy.execute();}
}// 測試入口
public class StrategyDemo {public static void main(String[] args) {Context contextA = new Context(new ConcreteStrategyA());contextA.executeStrategy();Context contextB = new Context(new ConcreteStrategyB());contextB.executeStrategy();}
}
責任鏈模式
將請求的處理對象連成一條鏈,每個處理者持有對下一個處理者的引用,按順序處理請求或將其傳遞給下一個處理者。
當一個請求可能由多個對象處理,但不清楚到底由哪一個對象處理時,可采用責任鏈模式進行動態分派。
在 Spring Security 中,FilterChainProxy
維護了一系列過濾器(Filter),每個過濾器依次處理 HTTP
請求,決定是否放行、拒絕或進一步處理。
Spring MVC 中的攔截器鏈(HandlerInterceptor
)也是一個責任鏈,每個攔截器按順序處理請求的預處理和后處理工作。
// 責任鏈中的抽象處理者
public abstract class Handler {protected Handler next;// 設置下一個處理者public void setNext(Handler next) {this.next = next;}// 處理請求public abstract void handleRequest(String request);
}// 具體處理者A
public class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(String request) {if (request.contains("A")) {System.out.println("ConcreteHandlerA 處理請求: " + request);} else if (next != null) {next.handleRequest(request);}}
}// 具體處理者B
public class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(String request) {if (request.contains("B")) {System.out.println("ConcreteHandlerB 處理請求: " + request);} else if (next != null) {next.handleRequest(request);}}
}// 測試責任鏈模式
public class ChainDemo {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();// 設置責任鏈順序handlerA.setNext(handlerB);// 測試請求:包含 "B" 的請求由 ConcreteHandlerB 處理handlerA.handleRequest("Request with B");// 測試請求:包含 "A" 的請求由 ConcreteHandlerA 處理handlerA.handleRequest("Request with A");}
}