第11章 Abstract Factory模式

Abstract Factory模式:抽象工厂模式,为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。

Abstract Factory模式:关键特征

意图:需要为特定的客户提供对象组。

问题:需要实例化一组相关的对象。

解决方案:协调对象组的创建。提供一种方式,将如何执行对象实例化的规则从使用这些对象的客户对象提取出来。

参与者与协作者:AbstractFactory为如何创建对象组的每个成员定义接口。一般每个组都由独立的ConcreteFactory进行创建。

效果:这个模式将“使用哪些对象”的规则与“如何使用这些对象”的逻辑分离开来。

实现:定义一个抽象类来指定创建哪些对象。然后为每个组实现一个具体类。可以用表或文件完成同样的任务。 

假设您要制作一个对话方块(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 类别图展现这种概念。


现在如果要更换所有的视感元件,就只要抽象掉具体的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
public class WindowsTextField implements ITextField {
public void paintTextField() {
System.out.println("Windows textField paints....");
}
}


  • 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结构图:


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

你可能感兴趣的:(第11章 Abstract Factory模式)