抽象工厂

维基百科,自由的百科全书

(重定向自抽象工厂模式)
跳转到: 导航, 搜索
Abstract factory UML class diagram

抽象工厂模式(Abstact Factory)是一种常见的软件设计模式。该模式为一个产品族提供了统一的创建接口。当需要这个产品族的某一系列的时候,可以从抽象工厂中选出相应的系列创建一个具体的工厂类。

目录

[编辑] 例子

假设我们有两种产品接口 Button 和 Border ,每一种产品都支持多种系列,比如 Mac 系列和 Windows 系列。这样每个系列的产品分别是 MacButton, WinButton, MacBorder, WinBorder 。为了可以在运行时刻创建一个系列的产品族,我们可以为每个系列的产品族建立一个工厂 MacFactory 和 WinFactory 。每个工厂都有两个方法 CreateButton 和 CreateBorder 并返回对应的产品,可以将这两个方法抽象成一个接口 AbstractFactory 。这样在运行时刻我们可以选择创建需要的产品系列。

[编辑] C++ 示例代码

我们的产品结构是这样的

class Button; // Abstract Class
 
class MacButton: public Button {};
 
class WinButton: public Button {};
 
class Border; // Abstract Class
 
class MacBorder: public Border {};
 
class WinBorder: public Border {};

对应的工厂是这样的

class AbstractFactory {
public:
    virtual Button* CreateButton() =0;
    virtual Border* CreateBorder() =0;
};
 
class MacFactory: public AbstractFactory {
public:
    MacButton* CreateButton() { return new MacButton; }
    MacBorder* CreateBorder() { return new MacBorder; }
};
 
class WinFactory: public AbstractFactory {
public:
    WinButton* CreateButton() { return new WinButton; }
    WinBorder* CreateBorder() { return new WinBorder; }
};

那么客户可以根据需要选择 Mac 风格或者 Win 风格的 Button 或 Border 来创建

AbstractFactory* fac;
switch (style) {
case MAC:
    fac = new MacFactory;
    break;
case WIN:
    fac = new WinFactory;
    break;
}
Button* button = fac->CreateButton();
Border* border = fac->CreateBorder();

[编辑] PHP示例代码

<?php
/***************************************************************************
 *              AbstractFactory.php
 *              -------------------
 *   Time  :    2006-11-11
 *   Coder :    rollenc(http://www.rollenc.com)
 *              syre(http://syre.blogbus.com)
 ***************************************************************************/
abstract class AbstractFactory {
	abstract public function CreateButton();
	abstract public function CreateBorder();
}
 
class MacFactory extends AbstractFactory{
	public function CreateButton()
	{
 
		return new MacButton();
	}
	public function CreateBorder()
	{
		return new MacBorder();
	}
}
class WinFactory extends AbstractFactory{
	public function CreateButton()
	{
		return new WinButton();
	}
	public function CreateBorder()
	{
		return new WinBorder();
	}
}
class Button{}
class Border{}
 
class MacButton extends Button{
	function __construct()
	{
		echo 'MacButton is created' . "\n";
	}
}
class MacBorder extends Border{
	function __construct()
	{
		echo 'MacBorder is created' . "\n";
	}
}
 
 
class WinButton extends AbstractButton{
	function __construct()
	{
		echo 'WinButton is created' . "\n";
	}
}
class WinBorder extends AbstractBorder{
	function __construct()
	{
		echo 'WinBorder is created' . "\n";
	}
}
?>

那么客户可以根据需要选择 Mac 风格或者 Win 风格的 Button 或 Border 来创建

<?
$type = 'Mac'; //value by user.
if(!in_array($type, array('Win','Mac'))
    die('Type Error');
$factoryClass = $type.'Factory';
$factory=new $factoryClass;
$factory->CreateButton();
$factory->CreateBorder();
?>

[编辑] Java程式範例

  • 首先建立描述一個人基本資料的 PersonInterface
package tw.idv.javax.demo.Interface;
 
import java.util.Calendar;
 
public interface PersonInterface {
 
	public static final String ROLE = PersonInterface.class.getName();
 
	public abstract String getId() throws Exception;
 
	public abstract void setId(String id) throws Exception;
 
	public abstract String getName() throws Exception;
 
	public abstract void setName(String name) throws Exception;
 
	public abstract Calendar getBirthday() throws Exception;
 
	public abstract void setBirthday(Calendar birthday) throws Exception;
 
}
  • 接著實作描述一個人基本資料的 抽象 PersonInterfaceImpl
package tw.idv.javax.demo.Implements;
 
import java.util.Calendar;
 
import tw.idv.javax.demo.Interface.PersonInterface;
 
public abstract class PersonInterfaceImpl implements PersonInterface {
 
	private String id = null;
 
	private String name = null;
 
	private Calendar birthday = null;
 
	public String getId() {
		return id;
	}
 
	public void setId(String id) {
		this.id = id;
	}
 
	public String getName() {
		return name;
	}
 
	public void setName(String name) {
		this.name = name;
	}
 
	public Calendar getBirthday() {
		return birthday;
	}
 
	public void setBirthday(Calendar birthday) {
		this.birthday = birthday;
	}
 
}
  • 接著繼承 PersonInterfaceImpl ,寫一個描述孩童基本資料 Children
package tw.idv.javax.demo.Extends;
 
import tw.idv.javax.demo.Implements.PersonInterfaceImpl;
 
public class Children extends PersonInterfaceImpl {
 
}
  • 接著繼承 PersonInterfaceImpl ,寫一個描述成人基本資料 Adult
package tw.idv.javax.demo.Extends;
 
import tw.idv.javax.demo.Implements.PersonInterfaceImpl;
 
public class Adult extends PersonInterfaceImpl {
 
	private int income = 0;
 
	public int getIncome() {
		return income;
	}
 
	public void setIncome(int income) {
		this.income = income;
	}
 
}
  • 比較這幾個class,你會發現 Interface 其實只是在定義一個架構,並有實際的邏輯程式,

而要实现 interface 時,若是還有其他物件需要繼承你正要实现的 class 時,你最好把你要 实现的 class ,定義為 abstract class 。

[编辑] 适用性

在以下情况可以使用Abstract Factory模式

  • 一个系统要独立于它的产品的创建、组合和表示时。
  • 一个系统要由多个产品系列中的一个来配置时。
  • 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
  • 当你提供一个产品类库,而只想显示它们的接口而不是实现时。

[编辑] 优点

  1. 具体产品从客户代码中被分离出来
  2. 容易改变产品的系列
  3. 将一个系列的产品族统一到一起创建

[编辑] 缺点

  1. 在产品族中扩展新的产品是很困难的,它需要修改抽象工厂的接口

[编辑] 相关模式

工厂方法模式
工厂类通常用工厂方法模式实现
单例模式
具体工厂通常只需要一个实例
个人工具