Abstract Factory 模式

假如你要制作一个对话框控件,你希望这个对话框可以有不同的Look&Feel,最基本的想法是,使用setter将不同的Look&Feel注入到这个对话框,例如:

CustomDialog.java

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两个界面,而不是其实作类别,不过这里还有一个进一步的要求,使用上面的方式还必须亲自调用setter、layout等方法。如果你希望皮肤的更换可以更加简单些,例如只需要透过一个元件的替换就可以完成对话框所有元件的观感更换。

你可以使用Abstract Factory模式,将所有的对话框需要产生的元件加以封装,对话框依赖于Abstract Factory,实际上具体的Factory的实现则分别产生对话框所需要的控件,下面的UML类图将展示这种概念。
[img]/upload/attachment/88969/6fb0b1fe-4d8c-3fc0-9498-174dfed90029.jpg[/img]

现在如果要更换所有的控件,只需要注入具体的Factory就可以了,例如:
CustomDialog windowsDialog =
new CustomDialog(new WindowsWidgetFactory());
windowsDialog.showDialog();

CustomDialog macDialog =
new CustomDialog(new MacWidgetFactory());
macDialog.showDialog();


将上面的UML图实现出来:
CustomDialog.java
public class CustomDialog {
private IButton button;
private ITextField textField;

public CustomDialog(IWidgetFactory widgetFactory) {
setWidgetFactory(widgetFactory);
}

// 由于客户端只依赖于抽象工厂,工厂如何运作跟客户端无关。
// 要抽换工厂并不需要改动客户端程序
public void setWidgetFactory(IWidgetFactory widgetFactory) {
setButton(widgetFactory.createButton());
setTextField(widgetFactory.createTextField());
// ....
}

public void layoutAllComponents() {
// layout all components
}

// 这里也是依赖抽象,实际改变控件实例
// 客户端代码也不需要修改
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....");
}
}


IButton.java

public interface IButton {
public void paintButton();
}


ITextField.java

public interface ITextField {
public void paintTextField();
}


IWidgetFactory.java

public interface IWidgetFactory {
public IButton createButton();
public ITextField createTextField();
}


MacButton.java
public class MacButton implements IButton {
public void paintButton() {
System.out.println("Mac button paints....");
}
}


WindowsButton.java
public class WindowsButton implements IButton {
public void paintButton() {
System.out.println("Windows button paints....");
}
}


MacTextField.java
public class MacTextField implements ITextField {
public void paintTextField() {
System.out.println("Mac textField paints....");
}
}


WindowsTextField.java
public class WindowsTextField implements ITextField {
public void paintTextField() {
System.out.println("Windows textField paints....");
}
}


MacWidgetFactory.java
public class MacWidgetFactory implements IWidgetFactory {
public IButton createButton() {
return new MacButton();
}

public ITextField createTextField() {
return new MacTextField();
}
}


WindowsWidgetFactory.java
public class WindowsWidgetFactory 
implements IWidgetFactory {
public IButton createButton() {
return new WindowsButton();
}

public ITextField createTextField() {
return new WindowsTextField();
}
}


下图是Abstract Factory模式的UML结构图:
[img]/upload/attachment/88978/2848dc85-a5d8-350a-8df4-f731af531f6e.jpg[/img]
简单的说,在Abstract Factory模式中将具体的Product封装在Factory实现中,而库户仍只要面对Factory与Product的抽象界面,避免依赖于具体的Factory与Product,由于Factory封装了所有必须的Product,所以要更换所有的控件,只需要简单地替换掉Factory的具体实现就可以了,不需要修改客户端的程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值