Proxy Pattern 是一種靜態設計模式,它可以將物件的存取權限控制在一個代理物件中,代理物件可以在真實的物件之前或之後執行一些額外的功能,例如遠端代理、虛擬代理、安全代理等。通過使用代理模式,客戶端可以透明地訪問一個物件,而不需要知道它的實際實現細節。
舉例來說,假設有一個 Image 接口,它有一個 display() 方法用來顯示圖片,一個 RealImage 類用來實現 Image 接口,另外還有一個 ProxyImage 類也實現了 Image 接口,它在顯示圖片之前先檢查是否有權限。
interface Image {
void display();
}
class RealImage implements Image {
private String imagePath;
RealImage(String imagePath) {
this.imagePath = imagePath;
loadImageFromDisk();
}
private void loadImageFromDisk() {
System.out.println("Loading image from disk: " + imagePath);
}
@Override
public void display() {
System.out.println("Displaying image: " + imagePath);
}
}
class ProxyImage implements Image {
private RealImage realImage;
private String imagePath;
ProxyImage(String imagePath) {
this.imagePath = imagePath;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(imagePath);
}
realImage.display();
}
}
public class Main {
public static void main(String[] args) {
Image image = new ProxyImage("test.jpg");
image.display();
}
}
在上面的例子中,當使用 ProxyImage 類顯示圖片時,它首先會檢查是否有權限,如果沒有權限,就不會顯示圖片;如果有權限,就會調用 RealImage 的 display() 方法來顯示圖片。這讓客戶端可以透明地訪問圖片,而不需要知道代理物件是否存在。
答案:
public interface WebPage {
public void display();
}
public class RealWebPage implements WebPage {
private String url;
public RealWebPage(String url) {
this.url = url;
load();
}
private void load() {
System.out.println("Loading " + url);
}
public void display() {
System.out.println("Displaying " + url);
}
}
public class ProxyWebPage implements WebPage {
private RealWebPage realWebPage;
public ProxyWebPage(String url) {
// 如果網址是 "dangerous.com",則在實現 WebPage 的顯示方法顯示 "Dangerous Site",否則顯示網址本身
if (url.equals("dangerous.com")) {
System.out.println("Access Denied");
} else {
realWebPage = new RealWebPage(url);
}
}
public void display() {
if (realWebPage != null) {
realWebPage.display();
}
}
}
答案:
public interface Image {
void display();
}
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading " + filename);
}
public void display() {
System.out.println("Displaying " + filename);
}
}
public class ProxyImage implements Image {
private RealImage image;
private String filename;
public ProxyImage(String filename) {
this.filename = filename;
}
public void display() {
if (image == null) {
image = new RealImage(filename);
}
image.display();
}
}
答案:
public interface MusicPlayer {
void playMusic();
}
public class RealMusicPlayer implements MusicPlayer {
private String song;
public RealMusicPlayer(String song) {
this.song = song;
loadMusic();
}
private void loadMusic() {
System.out.println("Loading " + song);
}
public void playMusic() {
System.out.println("Playing " + song);
}
}
public class MusicPlayerProxy implements MusicPlayer {
private String username;
private String password;
private RealMusicPlayer realMusicPlayer;
public MusicPlayerProxy(String username, String password, String song) {
this.username = username;
this.password = password;
// 檢查使用者帳號是否有付費。如果有付費,則需要建立 RealMusicPlayer 物件,否則將不會建立
if (isPaidUser(username, password)) {
realMusicPlayer = new RealMusicPlayer(song);
} else {
System.out.println("Access Denied");
}
}
public void playMusic() {
if (realMusicPlayer != null) {
realMusicPlayer.playMusic();
}
}
private boolean isPaidUser(String username, String password) {
// 檢查使用者是否有付費帳號
return true;
}
}
答案:
public interface Database {
void save(String data);
}
public class RealDatabase implements Database {
public void save(String data) {
System.out.println("Saving " + data);
// 將 data 寫入到資料庫中
}
}
public class DatabaseProxy implements Database {
private RealDatabase realDatabase;
private List<String> buffer = new ArrayList<String>();
private int bufferSize = 10;
public void save(String data) {
if (realDatabase == null) {
realDatabase = new RealDatabase();
}
buffer.add(data);
if (buffer.size() >= bufferSize) {
for (String s : buffer) {
realDatabase.save(s);
}
buffer.clear();
}
}
}
答案:
public interface MessengerWindow {
void display();
}
public class RealMessengerWindow implements MessengerWindow {
private String username;
public RealMessengerWindow(String username) {
this.username = username;
openWindow();
}
private void openWindow() {
System.out.println("Opening chat window for " + username);
}
public void display() {
System.out.println("Chatting with " + username);
}
}
public class MessengerWindowProxy implements MessengerWindow {
private static Map<String, RealMessengerWindow> chatWindows = new HashMap<String, RealMessengerWindow>();
private String username;
public MessengerWindowProxy(String username) {
this.username = username;
}
public void display() {
if (!chatWindows.containsKey(username)) {
chatWindows.put(username, new RealMessengerWindow(username));
}
chatWindows.get(username).display();
}
}