fbpx
维基百科

抽象工厂

抽象工厂模式(英語:Abstract factory pattern)是一种软件开发设计模式。抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道(或关心)它从这些内部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。

統一塑模語言中的類別圖來表示抽象工廠

举个例子来说,比如一个抽象工厂类叫做DocumentCreator(文档创建器),此类提供创建若干种产品的接口,包括createLetter()(创建信件)和createResume()(创建简历)。其中,createLetter()返回一个Letter(信件),createResume()返回一个Resume(简历)。系统中还有一些DocumentCreator的具体实现类,包括FancyDocumentCreatorModernDocumentCreator。这两个类对DocumentCreator的两个方法分别有不同的实现,用来创建不同的“信件”和“简历”(用FancyDocumentCreator的实例可以创建FancyLetterFancyResume,用ModernDocumentCreator的实例可以创建ModernLetterModernResume)。这些具体的“信件”和“简历”类均继承自抽象类,即LetterResume类。客户端需要创建“信件”或“简历”时,先要得到一个合适的DocumentCreator实例,然后调用它的方法。一个工厂中创建的每个对象都是同一个主题的(“fancy”或者“modern”)。客户端程序只需要知道得到的对象是“信件”或者“简历”,而不需要知道具体的主题,因此客户端程序从抽象工厂DocumentCreator中得到了LetterResume类的引用,而不是具体类的对象引用。

“工厂”是创建产品(对象)的地方,其目的是将产品的创建与产品的使用分离。抽象工厂模式的目的,是将若干抽象产品的接口与不同主题产品的具体实现分离开。这样就能在增加新的具体工厂的时候,不用修改引用抽象工厂的客户端代码。

使用抽象工厂模式,能够在具体工厂变化的时候,不用修改使用工厂的客户端代码,甚至是在运行时。然而,使用这种模式或者相似的设计模式,可能给编写代码带来不必要的复杂性和额外的工作。正确使用设计模式能够抵消这样的“额外工作”。

定义 编辑

抽象工厂模式的实质是“提供接口,创建一系列相关或独立的对象,而不指定这些对象的具体类。”[1]

使用 编辑

具体的工厂决定了创建对象的具体类型,而且工厂就是对象实际创建的地方(比如在C++中,用“new”操作符创建对象)。然而,抽象工厂只返回一个指向创建的对象的抽象引用(或指针)。

这样,客户端程序调用抽象工厂引用的方法,由具体工厂完成对象创建,然后客户端程序得到的是抽象产品的引用。如此使客户端代码与对象的创建分离开来。[2]

因为工厂仅仅返回一个抽象产品的引用(或指针),所以客户端程序不知道(也不会牵绊于)工厂创建对象的具体类型。然而,工厂知道具体对象的类型;例如,工厂可能从配置文件中读取某种类型。这时,客户端没有必要指定具体类型,因为已经在配置文件中指定了。通常,这意味着:

  • 客户端代码不知道任何具体类型,也就没必要引入任何相关的头文件或类定义。客户端代码仅仅处理抽象类型。工厂确实创建了具体类型的对象,但是客户端代码仅使用这些对象的抽象接口来访问它们。[3]
  • 如果要增加一个具体类型,只需要修改客户端代码使用另一个工厂即可,而且这个修改通常只是一个文件中的一行代码。不同的工厂创建不同的具体类型的对象,但是和以前一样返回一个抽象类型的引用(或指针),因此客户端代码的其他部分不需要任何改动。这样比修改客户端代码创建新类型的对象简单多了。如果是后者的话,需要修改代码中每一个创建这种对象的地方(而且需要注意的是,这些地方都知道对象的具体类型,而且需要引入具体类型的头文件或类定义)。如果所有的工厂对象都存储在全局的单例对象中,所有的客户端代码到这个单例中访问需要的工厂,那么,更换工厂就非常简单了,仅仅需要更改这个单例对象即可。[3]

结构 编辑

LePUS3图 编辑

 

类图 编辑

 

GuiFactory接口中的createButton方法返回Button类型的对象。返回Button的哪种实现依赖于使用GuiFactory的哪种实现。

需要注意的是,为了简洁起见,以上类图仅仅展示了创建一个类型对象的工厂。而在抽象工厂模式中,通常一个工厂能够创建若干种不同类型的对象。

代码举例 编辑

假设我们有两种产品接口 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 Button{ function __construct() { echo 'WinButton is created' . "\n"; } } class WinBorder extends Border{ 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 编辑

  • 使用上面的例子
public interface Button {} public interface Border {} 
  • 实现抽象类
public class MacButton implements Button {} public class MacBorder implements Border {} public class WinButton implements Button {} public class WinBorder implements Border {} 
  • 接着实现工厂
public class MacFactory { public static Button createButton() {  return new MacButton(); } public static Border createBorder() {  return new MacBorder(); } } 
public class WinFactory { public static Button createButton() {  return new WinButton(); } public static Border createBorder() {  return new WinBorder(); } } 

适用性 编辑

在以下情况可以考虑使用抽象工廠模式:

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

優點 编辑

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

缺點 编辑

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

参考文献 编辑

  1. ^ [Erich]; Richard Helm, Ralph Johnson, John M. Vlissides. Design Patterns: Abstract Factory (HTML). informIT. 2009-10-23 [2012-05-16]. (原始内容于2021-03-22) (英语). Object Creational: Abstract Factory: Intent: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.  请检查|author-link1=值 (帮助)
  2. ^ [David]. Object Design for the Perplexed (HTML). The Code Project. 2009-10-23 [2012-05-16]. (原始内容于2011-02-21) (英语). The factory insulates the client from changes to the product or how it is created, and it can provide this insulation across objects derived from very different abstract interfaces.  请检查|author-link1=值 (帮助)
  3. ^ 3.0 3.1 Abstract Factory: Implementation (HTML). OODesign.com. [2012-05-16]. (原始内容于2021-03-10) (英语). 

参见 编辑


抽象工厂, 模式, 英語, abstract, factory, pattern, 是一种软件开发设计模式, 模式提供了一种方式, 可以将一组具有同一主题的单独的工厂封装起来, 在正常使用中, 客户端程序需要创建的具体实现, 然后使用作为接口来创建这一主题的具体对象, 客户端程序不需要知道, 或关心, 它从这些内部的工厂方法中获得对象的具体类型, 因为客户端程序仅使用这些对象的通用接口, 模式将一组对象的实现细节与他们的一般使用分离开来, 以統一塑模語言中的類別圖來表示抽象工廠, 举个例子来说, 比如一个类叫做do. 抽象工厂模式 英語 Abstract factory pattern 是一种软件开发设计模式 抽象工厂模式提供了一种方式 可以将一组具有同一主题的单独的工厂封装起来 在正常使用中 客户端程序需要创建抽象工厂的具体实现 然后使用抽象工厂作为接口来创建这一主题的具体对象 客户端程序不需要知道 或关心 它从这些内部的工厂方法中获得对象的具体类型 因为客户端程序仅使用这些对象的通用接口 抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来 以統一塑模語言中的類別圖來表示抽象工廠 举个例子来说 比如一个抽象工厂类叫做DocumentCreator 文档创建器 此类提供创建若干种产品的接口 包括createLetter 创建信件 和createResume 创建简历 其中 createLetter 返回一个Letter 信件 createResume 返回一个Resume 简历 系统中还有一些DocumentCreator的具体实现类 包括FancyDocumentCreator和ModernDocumentCreator 这两个类对DocumentCreator的两个方法分别有不同的实现 用来创建不同的 信件 和 简历 用FancyDocumentCreator的实例可以创建FancyLetter和FancyResume 用ModernDocumentCreator的实例可以创建ModernLetter和ModernResume 这些具体的 信件 和 简历 类均继承自抽象类 即Letter和Resume类 客户端需要创建 信件 或 简历 时 先要得到一个合适的DocumentCreator实例 然后调用它的方法 一个工厂中创建的每个对象都是同一个主题的 fancy 或者 modern 客户端程序只需要知道得到的对象是 信件 或者 简历 而不需要知道具体的主题 因此客户端程序从抽象工厂DocumentCreator中得到了Letter或Resume类的引用 而不是具体类的对象引用 工厂 是创建产品 对象 的地方 其目的是将产品的创建与产品的使用分离 抽象工厂模式的目的 是将若干抽象产品的接口与不同主题产品的具体实现分离开 这样就能在增加新的具体工厂的时候 不用修改引用抽象工厂的客户端代码 使用抽象工厂模式 能够在具体工厂变化的时候 不用修改使用工厂的客户端代码 甚至是在运行时 然而 使用这种模式或者相似的设计模式 可能给编写代码带来不必要的复杂性和额外的工作 正确使用设计模式能够抵消这样的 额外工作 目录 1 定义 2 使用 3 结构 3 1 LePUS3图 3 2 类图 4 代码举例 4 1 C 4 2 PHP 4 3 Java 5 适用性 6 優點 7 缺點 8 参考文献 9 参见定义 编辑抽象工厂模式的实质是 提供接口 创建一系列相关或独立的对象 而不指定这些对象的具体类 1 使用 编辑具体的工厂决定了创建对象的具体类型 而且工厂就是对象实际创建的地方 比如在C 中 用 new 操作符创建对象 然而 抽象工厂只返回一个指向创建的对象的抽象引用 或指针 这样 客户端程序调用抽象工厂引用的方法 由具体工厂完成对象创建 然后客户端程序得到的是抽象产品的引用 如此使客户端代码与对象的创建分离开来 2 因为工厂仅仅返回一个抽象产品的引用 或指针 所以客户端程序不知道 也不会牵绊于 工厂创建对象的具体类型 然而 工厂知道具体对象的类型 例如 工厂可能从配置文件中读取某种类型 这时 客户端没有必要指定具体类型 因为已经在配置文件中指定了 通常 这意味着 客户端代码不知道任何具体类型 也就没必要引入任何相关的头文件或类定义 客户端代码仅仅处理抽象类型 工厂确实创建了具体类型的对象 但是客户端代码仅使用这些对象的抽象接口来访问它们 3 如果要增加一个具体类型 只需要修改客户端代码使用另一个工厂即可 而且这个修改通常只是一个文件中的一行代码 不同的工厂创建不同的具体类型的对象 但是和以前一样返回一个抽象类型的引用 或指针 因此客户端代码的其他部分不需要任何改动 这样比修改客户端代码创建新类型的对象简单多了 如果是后者的话 需要修改代码中每一个创建这种对象的地方 而且需要注意的是 这些地方都知道对象的具体类型 而且需要引入具体类型的头文件或类定义 如果所有的工厂对象都存储在全局的单例对象中 所有的客户端代码到这个单例中访问需要的工厂 那么 更换工厂就非常简单了 仅仅需要更改这个单例对象即可 3 结构 编辑LePUS3图 编辑 nbsp 类图 编辑 nbsp GuiFactory接口中的createButton方法返回Button类型的对象 返回Button的哪种实现依赖于使用GuiFactory的哪种实现 需要注意的是 为了简洁起见 以上类图仅仅展示了创建一个类型对象的工厂 而在抽象工厂模式中 通常一个工厂能够创建若干种不同类型的对象 代码举例 编辑假设我们有两种产品接口 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 gt CreateButton Border border fac gt CreateBorder PHP 编辑 lt 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 Button function construct echo WinButton is created n class WinBorder extends Border function construct echo WinBorder is created n gt 那么客户可以根据需要选择 Mac 风格或者 Win 风格的 Button 或 Border 来创建 lt type Mac value by user if in array type array Win Mac die Type Error factoryClass type Factory factory new factoryClass factory gt CreateButton factory gt CreateBorder gt Java 编辑 使用上面的例子 public interface Button public interface Border 实现抽象类 public class MacButton implements Button public class MacBorder implements Border public class WinButton implements Button public class WinBorder implements Border 接着实现工厂 public class MacFactory public static Button createButton return new MacButton public static Border createBorder return new MacBorder public class WinFactory public static Button createButton return new WinButton public static Border createBorder return new WinBorder 适用性 编辑在以下情况可以考虑使用抽象工廠模式 一个系统要独立于它的产品的创建 组合和表示时 一个系统要由多个产品系列中的一个来配置时 需要强调一系列相关的产品对象的设计以便进行联合使用时 提供一个产品类库 而只想显示它们的接口而不是实现时 優點 编辑具体产品从客户代码中被分离出来 容易改变产品的系列 将一个系列的产品族统一到一起创建缺點 编辑在产品族中扩展新的产品是很困难的 它需要修改抽象工厂的接口参考文献 编辑 Erich Richard Helm Ralph Johnson John M Vlissides Design Patterns Abstract Factory HTML informIT 2009 10 23 2012 05 16 原始内容存档于2021 03 22 英语 Object Creational Abstract Factory Intent Provide an interface for creating families of related or dependent objects without specifying their concrete classes 引文使用过时参数coauthors 帮助 请检查 author link1 值 帮助 David Object Design for the Perplexed HTML The Code Project 2009 10 23 2012 05 16 原始内容存档于2011 02 21 英语 The factory insulates the client from changes to the product or how it is created and it can provide this insulation across objects derived from very different abstract interfaces 请检查 author link1 值 帮助 3 0 3 1 Abstract Factory Implementation HTML OODesign com 2012 05 16 原始内容存档于2021 03 10 英语 参见 编辑工廠方法模式 單例模式 设计模式 计算机 取自 https zh wikipedia org w index php title 抽象工厂 amp oldid 77560341, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。