假設(shè)您要製作一個(gè)對(duì)話方塊(Dialog)元件,您希望的是這個(gè)對(duì)話方塊可以有不同的視感(Look-and- feel),最基本的想法是,藉由Setter將不同視感的元件設(shè)定給這個(gè)對(duì)話方塊,例如:
public class CustomDialog {
private IButton button;
private ITextField textField;
public void setButton(IButton button) {
this.button = button;
}
public void setTextField(ITextField textField) {
this.textField = textField;
}
public void layoutAllComponents() {
// ....
}
public void showDialog() {
this.paintDialog();
button.paintButton();
textField.paintTextField();
}
public void paintDialog() {
System.out.println("custom dialog paints....");
}
}
很簡單,這是最基本的介面依賴,Setter依賴於IButton與ITextField兩個(gè)介面,而不是其實(shí)作類別,不過這邊還有個(gè)進(jìn)一步的要求,使用上面的方式還必須親自呼叫Setter、layout等方法,您希望視感的更換可以更簡單些,例如只要透一個(gè)元件的替換就可以完成對(duì)話方塊上所有元件的視感更換。
您可以使用Abstract Factory模式,將所有對(duì)話方塊所需要的產(chǎn)生的元件加以封裝,對(duì)話方塊依賴於Abstract Factory,實(shí)際上具體的Factory實(shí)現(xiàn)則分別產(chǎn)生對(duì)話方塊所需要的視感元件,下面的 UML 類別圖展現(xiàn)這種概念。
現(xiàn)在如果要更換所有的視感元件,就只要抽象掉具體的Factory就可以了,例如:
CustomDialog windowsDialog =
new CustomDialog(new WindowsWidgetFactory());
windowsDialog.showDialog();
CustomDialog macDialog =
new CustomDialog(new MacWidgetFactory());
macDialog.showDialog();
來將上面的UML圖具體實(shí)現(xiàn)出來。
public class CustomDialog {
private IButton button;
private ITextField textField;
public CustomDialog(IWidgetFactory widgetFactory) {
setWidgetFactory(widgetFactory);
}
// 由於客戶端只依賴於抽象的工廠,工廠如何實(shí)作並無關(guān)客戶端的事
// 要抽換工廠並不需要改動(dòng)客戶端的程式
public void setWidgetFactory(IWidgetFactory widgetFactory) {
setButton(widgetFactory.getButton());
setTextField(widgetFactory.getTextField());
}
public void layoutAllComponents() {
// layout all components
}
// 這邊也是依賴抽象,實(shí)際改變了元件實(shí)例
// 客戶端代碼也不用更改
public void setButton(IButton button) {
this.button = button;
}
public void setTextField(ITextField textField) {
this.textField = textField;
}
public void showDialog() {
this.paintDialog();
button.paintButton();
textField.paintTextField();
}
public void paintDialog() {
System.out.println("custom dialog paints....");
}
}
public interface IButton {
public void paintButton();
}
public interface ITextField {
public void paintTextField();
}
public interface IWidgetFactory {
public IButton getButton();
public ITextField getTextField();
}
public class MacButton implements IButton {
public void paintButton() {
System.out.println("Mac button paints....");
}
}
public class WindowsButton implements IButton {
public void paintButton() {
System.out.println("Windows button paints....");
}
}
public class MacTextField implements ITextField {
public void paintTextField() {
System.out.println("Mac textField paints....");
}
}
public class WindowsTextField implements ITextField {
public void paintTextField() {
System.out.println("Windows textField paints....");
}
}
public class MacWidgetFactory implements IWidgetFactory {
public IButton getButton() {
return new MacButton();
}
public ITextField getTextField() {
return new MacTextField();
}
}
- WindowsWidgetFactory.java
public class WindowsWidgetFactory
implements IWidgetFactory {
public IButton getButton() {
return new WindowsButton();
}
public ITextField getTextField() {
return new WindowsTextField();
}
}
下圖是Abstract Factory模式的UML結(jié)構(gòu)圖:
簡單的說,在Abstract Factory模式中將具體的Product封裝在具體Factory實(shí)現(xiàn)中,而客戶仍只要面對(duì)Factory與Product的抽象介面,避免依賴於具體的Factory與Product,由於Factory封裝了所必須的Product,所以要更換掉所有的元件,只要簡單的抽換掉Factory就可以了,不用修改客戶端的程式。