📄 abstractfactory.htm
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link rel="stylesheet" href="css/stdlayout.css" type="text/css">
<link rel="stylesheet" href="css/print.css" type="text/css">
<meta content="text/html; charset=gb2312" http-equiv="content-type">
<title>Abstract Factory 模式</title>
</head>
<body>
<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>
<h1><a href="CppGossip.html">Design Pattern: Abstract Factory 模式</a></h1>
假设您要制作一个对话方块(Dialog)元件,您希望的是这个对话方块可以有不同的视感(Look-and- feel),最基本的想法是,藉由Setter将不同视感的元件设定给这个对话方块,例如:<br>
<ul>
<li> CustomDialog.java</li>
</ul>
<pre>public class CustomDialog {<br> private IButton button;<br> private ITextField textField;<br> <br> public void setButton(IButton button) {<br> this.button = button; <br> }<br> <br> public void setTextField(ITextField textField) {<br> this.textField = textField;<br> }<br><br> public void layoutAllComponents() {<br> // ....<br> }<br> <br> public void showDialog() {<br> this.paintDialog();<br> button.paintButton();<br> textField.paintTextField();<br> }<br> <br> public void paintDialog() {<br> System.out.println("custom dialog paints....");<br> }<br>}</pre>
<br>
很简单,这是最基本的介面依赖,Setter依赖于IButton与ITextField两个介面,而不是其实作类别,不过这边还有个进一步的要求,使用
上面的方式还必须亲自呼叫Setter、layout等方法,您希望视感的更换可以更简单些,例如只要透一个元件的替换就可以完成对话方块上所有元件的视
感更换。<br>
<br>
您可以使用Abstract Factory模式,将所有对话方块所需要的产生的元件加以封装,对话方块依赖于Abstract Factory,实际上具体的Factory实现则分别产生对话方块所需要的视感元件,下面的 UML 类别图展现这种概念。<br>
<div style="text-align: center;"><img style="width: 673px; height: 307px;" alt="AbstractFactory" title="AbstractFactory" src="images/abstractFactory-1.jpg"></div>
<br>
现在如果要更换所有的视感元件,就只要抽象掉具体的Factory就可以了,例如:<br>
<div style="margin-left: 40px;"><span style="font-weight: bold; font-family: Courier New,Courier,monospace;">CustomDialog windowsDialog = </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> new CustomDialog(new WindowsWidgetFactory());</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">windowsDialog.showDialog();</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">CustomDialog macDialog = </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;"> new CustomDialog(new MacWidgetFactory());</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace;">
<span style="font-weight: bold; font-family: Courier New,Courier,monospace;">macDialog.showDialog();</span><br>
</div>
<br>
来将上面的UML图具体实现出来。<br>
<ul>
<li> CustomDialog.java
</li>
</ul>
<pre>public class CustomDialog {<br> private IButton button;<br> private ITextField textField;<br> <br> public CustomDialog(IWidgetFactory widgetFactory) {<br> setWidgetFactory(widgetFactory);<br> }<br> <br> // 由于客户端只依赖于抽象的工厂,工厂如何实作并无关客户端的事<br> // 要抽换工厂并不需要改动客户端的程式<br> public void setWidgetFactory(IWidgetFactory widgetFactory) {<br> setButton(widgetFactory.getButton());<br> setTextField(widgetFactory.getTextField());<br> <br> }<br><br> public void layoutAllComponents() {<br> // layout all components<br> }<br> <br> // 这边也是依赖抽象,实际改变了元件实例<br> // 客户端代码也不用更改<br> public void setButton(IButton button) {<br> this.button = button; <br> }<br> <br> public void setTextField(ITextField textField) {<br> this.textField = textField;<br> }<br> <br> public void showDialog() {<br> this.paintDialog();<br> button.paintButton();<br> textField.paintTextField();<br> }<br> <br> public void paintDialog() {<br> System.out.println("custom dialog paints....");<br> }<br>} <br></pre>
<br>
<ul>
<li> IButton.java
</li>
</ul>
<pre>public interface IButton {<br> public void paintButton();<br>} <br></pre>
<br>
<ul>
<li> ITextField.java
</li>
</ul>
<pre>public interface ITextField {<br> public void paintTextField();<br>} <br></pre>
<br>
<ul>
<li> IWidgetFactory.java
</li>
</ul>
<pre>public interface IWidgetFactory {<br> public IButton getButton();<br> public ITextField getTextField();<br>} <br></pre>
<br>
<ul>
<li> MacButton.java
</li>
</ul>
<pre>public class MacButton implements IButton {<br> public void paintButton() {<br> System.out.println("Mac button paints....");<br> }<br>} <br></pre>
<br>
<ul>
<li> WindowsButton.java
</li>
</ul>
<pre>public class WindowsButton implements IButton {<br> public void paintButton() {<br> System.out.println("Windows button paints....");<br> }<br>} <br></pre>
<br>
<ul>
<li> MacTextField.java
</li>
</ul>
<pre>public class MacTextField implements ITextField {<br> public void paintTextField() {<br> System.out.println("Mac textField paints....");<br> }<br>} <br></pre>
<br>
<ul>
<li> WindowsTextField.java
</li>
</ul>
<pre>public class WindowsTextField implements ITextField {<br> public void paintTextField() {<br> System.out.println("Windows textField paints....");<br> }<br>} <br></pre>
<br>
<ul>
<li> MacWidgetFactory.java
</li>
</ul>
<pre>public class MacWidgetFactory implements IWidgetFactory {<br> public IButton getButton() {<br> return new MacButton();<br> }<br> <br> public ITextField getTextField() {<br> return new MacTextField();<br> }<br>} <br></pre>
<br>
<ul>
<li> WindowsWidgetFactory.java
</li>
</ul>
<pre>public class WindowsWidgetFactory <br> implements IWidgetFactory {<br> public IButton getButton() {<br> return new WindowsButton();<br> }<br> <br> public ITextField getTextField() {<br> return new WindowsTextField();<br> }<br>}</pre>
<br>
下图是Abstract Factory模式的UML结构图:<br>
<div style="text-align: center;">
<div style="text-align: center;"><img style="width: 581px; height: 266px;" alt="AbstractFactory" title="AbstractFactory" src="images/abstractFactory-2.jpg"></div>
</div>
<br>
简单的说,在Abstract
Factory模式中将具体的Product封装在具体Factory实现中,而客户仍只要面对Factory与Product的抽象介面,避免依赖于具
体的Factory与Product,由于Factory封装了所必须的Product,所以要更换掉所有的元件,只要简单的抽换掉Factory就可以
了,不用修改客户端的程式。<br>
<br>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -