員工做違法網(wǎng)站seo顧問(wèn)賺錢(qián)嗎
上一篇地址:持續(xù)總結(jié)中!2024年面試必問(wèn) 20 道設(shè)計(jì)模式面試題(四)-CSDN博客
九、請(qǐng)解釋代理模式(Proxy Pattern)及其類(lèi)型。
代理模式(Proxy Pattern)是一種結(jié)構(gòu)設(shè)計(jì)模式,它為另一個(gè)對(duì)象提供一個(gè)代替或占位符的對(duì)象,以便控制對(duì)它的訪問(wèn)。代理模式可以在不直接與實(shí)際對(duì)象交互的情況下,提供對(duì)目標(biāo)對(duì)象的間接訪問(wèn)。這種模式在以下情況下非常有用:
- 當(dāng)需要對(duì)目標(biāo)對(duì)象的訪問(wèn)進(jìn)行控制時(shí)。
- 當(dāng)需要在訪問(wèn)對(duì)象時(shí)執(zhí)行額外的操作,如延遲初始化、訪問(wèn)前的權(quán)限檢查等。
- 當(dāng)需要為遠(yuǎn)程對(duì)象或復(fù)雜對(duì)象提供一種更簡(jiǎn)單的接口時(shí)。
代理模式的組成部分:
- 主題接口(Subject Interface):定義了真實(shí)對(duì)象和代理對(duì)象的共同接口,這樣代理可以代替真實(shí)對(duì)象被使用。
- 真實(shí)主題(Real Subject):定義了代理所代表的真實(shí)對(duì)象,實(shí)現(xiàn)了主題接口。
- 代理(Proxy):包含對(duì)真實(shí)主題的引用,實(shí)現(xiàn)了相同的主題接口,并控制對(duì)真實(shí)主題的訪問(wèn)。
代理模式的類(lèi)型:
-
遠(yuǎn)程代理(Remote Proxy):為位于不同地址空間的對(duì)象提供代理,隱藏對(duì)象位于遠(yuǎn)程地址空間的事實(shí)。它通常用在分布式系統(tǒng)中。
-
虛擬代理(Virtual Proxy):延遲創(chuàng)建開(kāi)銷(xiāo)較大的對(duì)象。當(dāng)?shù)谝淮涡枰獣r(shí),虛擬代理會(huì)加載并初始化真實(shí)對(duì)象。
-
保護(hù)代理(Protection Proxy):控制對(duì)原始對(duì)象的訪問(wèn),根據(jù)不同的訪問(wèn)權(quán)限提供不同的訪問(wèn)策略。
-
智能引用(Smart Reference):在訪問(wèn)對(duì)象時(shí)執(zhí)行額外的操作,如引用計(jì)數(shù)、線程安全檢查等。
-
緩存代理(Caching Proxy):為開(kāi)銷(xiāo)較大的操作結(jié)果提供存儲(chǔ),當(dāng)同樣的操作請(qǐng)求發(fā)生時(shí),可以直接使用緩存結(jié)果,避免重復(fù)計(jì)算。
-
同步代理(Synchronization Proxy):為多個(gè)線程提供同步訪問(wèn)某個(gè)對(duì)象的代理,確保在同一時(shí)間只有一個(gè)線程可以訪問(wèn)對(duì)象。
-
防火墻代理(Firewall Proxy):在網(wǎng)絡(luò)中控制對(duì)某些資源的訪問(wèn),提供安全控制。
-
復(fù)制代理(Copy Proxy):在復(fù)制一個(gè)復(fù)雜對(duì)象時(shí),復(fù)制代理可以優(yōu)化復(fù)制過(guò)程,例如按需復(fù)制。
示例:
假設(shè)我們有一個(gè)大型圖像處理對(duì)象,我們希望延遲其加載,直到真正需要顯示圖像時(shí)。使用虛擬代理模式,我們可以這樣實(shí)現(xiàn):
// 主題接口
interface ImageLoader {void load();void display();
}// 真實(shí)主題
class RealImageLoader implements ImageLoader {private String imagePath;public RealImageLoader(String imagePath) {this.imagePath = imagePath;}@Overridepublic void load() {System.out.println("Loading image from " + imagePath);}@Overridepublic void display() {System.out.println("Displaying image");}
}// 代理
class ImageProxy implements ImageLoader {private RealImageLoader realImageLoader;private String imagePath;public ImageProxy(String imagePath) {this.imagePath = imagePath;}@Overridepublic void load() {if (realImageLoader == null) {realImageLoader = new RealImageLoader(imagePath);realImageLoader.load();}}@Overridepublic void display() {if (realImageLoader != null) {realImageLoader.display();}}
}// 客戶端代碼
ImageLoader imageLoader = new ImageProxy("path/to/image.jpg");
imageLoader.display(); // 此時(shí)才加載圖像
在這個(gè)例子中,ImageProxy
類(lèi)作為 RealImageLoader
的代理,延遲了圖像的加載過(guò)程,直到 display()
方法被調(diào)用時(shí)才真正加載圖像。這展示了代理模式如何用于控制對(duì)資源的訪問(wèn)和執(zhí)行延遲初始化。
十、什么是命令模式(Command Pattern)?它在實(shí)際開(kāi)發(fā)中如何使用?
命令模式(Command Pattern)是一種行為設(shè)計(jì)模式,它將請(qǐng)求或操作封裝為一個(gè)對(duì)象。這種模式的主要目的是將發(fā)起請(qǐng)求的對(duì)象(調(diào)用者)與執(zhí)行請(qǐng)求的對(duì)象(接收者)解耦,從而讓不同的請(qǐng)求可以以統(tǒng)一的方式處理,例如執(zhí)行、排隊(duì)、記錄日志或撤銷(xiāo)等。
命令模式的組成部分:
- 命令接口(Command Interface):聲明執(zhí)行操作的方法,通常是一個(gè)?
execute()
?方法。 - 具體命令(Concrete Command):實(shí)現(xiàn)命令接口,對(duì)應(yīng)具體的操作,包含接收者對(duì)象的引用,并調(diào)用接收者的方法。
- 調(diào)用者(Invoker):要求命令對(duì)象執(zhí)行請(qǐng)求,通常包含一個(gè)或多個(gè)命令對(duì)象,并可以觸發(fā)命令的執(zhí)行。
- 接收者(Receiver):知道如何實(shí)施與執(zhí)行一個(gè)請(qǐng)求相關(guān)的操作,不直接與調(diào)用者或命令對(duì)象交互。
- 客戶端(Client):創(chuàng)建具體的命令對(duì)象,并設(shè)置它的接收者,然后將命令對(duì)象傳給調(diào)用者。
命令模式在實(shí)際開(kāi)發(fā)中的使用:
-
撤銷(xiāo)操作:命令模式可以很容易地實(shí)現(xiàn)撤銷(xiāo)功能。通過(guò)維護(hù)一個(gè)命令的歷史記錄,可以逐個(gè)撤銷(xiāo)命令的效果。
-
日志記錄:命令對(duì)象可以被用來(lái)記錄操作歷史,這對(duì)于審計(jì)和調(diào)試非常有用。
-
事務(wù)支持:命令模式可以支持事務(wù)性操作,確保一系列命令作為一個(gè)整體被執(zhí)行或回滾。
-
宏命令:可以將多個(gè)命令組合成一個(gè)宏命令,作為一個(gè)單獨(dú)的操作執(zhí)行。
-
異步命令執(zhí)行:命令模式可以用于實(shí)現(xiàn)異步操作,命令對(duì)象可以被發(fā)送到一個(gè)后臺(tái)線程執(zhí)行。
-
安全性:通過(guò)命令模式,可以控制哪些操作可以被執(zhí)行,哪些不可以,從而提高系統(tǒng)的安全性。
示例:
假設(shè)我們有一個(gè)簡(jiǎn)單的文本編輯器,它支持撤銷(xiāo)插入文本的操作。使用命令模式,我們可以這樣實(shí)現(xiàn):
// 命令接口
interface Command {void execute();void undo();
}// 接收者
class TextEditor {private StringBuilder content = new StringBuilder();public void type(String words) {content.append(words);}public void remove(int numberOfChars) {content.delete(content.length() - numberOfChars, content.length());}public String getContent() {return content.toString();}
}// 具體命令
class InsertCommand implements Command {private TextEditor editor;private String words;private int position;public InsertCommand(TextEditor editor, String words) {this.editor = editor;this.words = words;this.position = editor.getContent().length();}@Overridepublic void execute() {editor.type(words);}@Overridepublic void undo() {editor.remove(words.length());}
}// 調(diào)用者
class CommandInvoker {private Stack<Command> commandHistory = new Stack<>();public void setCommand(Command command) {command.execute();commandHistory.push(command);}public void undo() {if (!commandHistory.isEmpty()) {Command command = commandHistory.pop();command.undo();}}
}// 客戶端代碼
TextEditor editor = new TextEditor();
CommandInvoker invoker = new CommandInvoker();invoker.setCommand(new InsertCommand(editor, "Hello"));
invoker.setCommand(new InsertCommand(editor, " World"));
System.out.println(editor.getContent()); // 輸出: Hello Worldinvoker.undo(); // 撤銷(xiāo)插入 " World"
System.out.println(editor.getContent()); // 輸出: Hello
在這個(gè)例子中,InsertCommand
是一個(gè)具體命令,它封裝了插入文本的操作。TextEditor
是接收者,執(zhí)行實(shí)際的文本插入和刪除操作。CommandInvoker
是調(diào)用者,它維護(hù)了一個(gè)命令的歷史記錄,并可以執(zhí)行撤銷(xiāo)操作??蛻舳舜a通過(guò)調(diào)用者來(lái)執(zhí)行命令和撤銷(xiāo)操作,展示了命令模式如何在實(shí)際開(kāi)發(fā)中使用。