Design Pattern: Abstract Factory 模式

  假设您要制作一个对话方块(Dialog)元件,您希望的是这个对话方块可以有不同的视感(Look-and- feel),最基本的想法是,藉由Setter将不同视感的元件设定给这个对话方块,例如:
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 类别图展现这种概念。
abstractFactory-1.jpg
[img]http://dl.iteye.com/upload/attachment/0064/4136/9fc63bcf-fddc-372c-8c31-e8e8788da0d9.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.getButton());
setTextField(widgetFactory.getTextField());
}
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 getButton();
public ITextField getTextField();
}

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
[code]
public class WindowsTextField implements ITextField {
public void paintTextField() {
System.out.println("Windows textField paints....");
}
}
[/code]

MacWidgetFactory.java

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结构图:
abstractFactory-2.jpg

[img]http://dl.iteye.com/upload/attachment/0064/4138/32ee5e5e-dadf-3371-88a5-a2fd7152ac0d.jpg[/img]

  简单的说,在Abstract Factory模式中将具体的Product封装在具体Factory实现中,而客户仍只要面对Factory与Product的抽象介面,避免依赖于具体的Factory与Product,由于Factory封装了所必须的Product,所以要更换掉所有的元件,只要简单的抽换掉Factory就可以了,不用修改客户端的程式。

我的小结:Abstract Factory抽象工厂模式的用法是把窗体的具体部件和窗体分离开了,中间加入了工厂类,通过不同的工厂类来实现不改变窗体代码的情况下修改窗体的显示,只需设置不同的工厂类对象即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值