出自:http://www.cnblogs.com/libingql/archive/2012/12/09/2809754.html

1. 抽象工厂模式简介

1.1 定义

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

  抽象工厂可以向客户提供一个接口,是客户可以在不必指定产品具体类型的情况下,创建多个产品家族中的产品对象,它强调的“系列对象”的变化。

1.2 使用频率

   高

2. 抽象工厂模式结构

2.1 结构图

2.2 参与者

  抽象工厂模式参与者:

  ◊ AbstractFactory:声明一个创建抽象产品对象的操作接口

  ◊ ConcreteFactory:实现创建具体产品对象的操作

  ◊ AbstractProduct:声明一类产品对象接口

  ◊ Product

    °定义一个被相应具体工厂创建的产品对象

    °实现AbstractProduct接口

  ◊ Client:使用AbstractFactory和AbstractProduct类声明的接口

  在抽象工厂模式中,产品的创建由ConcreteFactory来完成,从结构图中可以看出,抽象工厂模式的ConcreteFactory不是负责一种具体Product的创建,而是负责一个Product族的创建。

3. 抽象工厂模式结构实现

  AbstractProductA.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Structural
{
public abstract class AbstractProductA
{
}
}

  AbstractProductB.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Structural
{
public abstract class AbstractProductB
{
public abstract void Interact(AbstractProductA a);
}
}

  ProductA1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Structural
{
public class ProductA1 : AbstractProductA
{
}
}

  ProductB1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Structural
{
public class ProductB1 : AbstractProductB
{
public override void Interact(AbstractProductA a)
{
Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name);
}
}
}

  ProductA2.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Structural
{
public class ProductA2 : AbstractProductA
{
}
}

  ProductB2.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Structural
{
public class ProductB2 : AbstractProductB
{
public override void Interact(AbstractProductA a)
{
Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name);
}
}
}

  ConcreteFactory1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Structural
{
public class ConcreteFactory1 : AbstractFactory
{
public override AbstractProductA CreateProductA()
{
return new ProductA1();
} public override AbstractProductB CreateProductB()
{
return new ProductB1();
}
}
}

  ConcreteFactory2.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Structural
{
public class ConcreteFactory2 : AbstractFactory
{
public override AbstractProductA CreateProductA()
{
return new ProductA2();
} public override AbstractProductB CreateProductB()
{
return new ProductB2();
}
}
}

  AbstractFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Structural
{
public abstract class AbstractFactory
{
public abstract AbstractProductA CreateProductA(); public abstract AbstractProductB CreateProductB();
}
}

  Client.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Structural
{
public class Client
{
private AbstractProductA _abstractProductA;
private AbstractProductB _abstractProductB; public Client(AbstractFactory factory)
{
_abstractProductB = factory.CreateProductB();
_abstractProductA = factory.CreateProductA();
} public void Run()
{
_abstractProductB.Interact(_abstractProductA);
}
}
}

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using DesignPatterns.AbstractFactoryPattern.Structural; namespace DesignPatterns.AbstractFactoryPattern
{
class Program
{
static void Main(string[] args)
{
// Abstract factory #1
AbstractFactory factory1 = new ConcreteFactory1();
Client client1 = new Client(factory1);
client1.Run(); // Abstract factory #2
AbstractFactory factory2 = new ConcreteFactory2();
Client client2 = new Client(factory2);
client2.Run(); // Wait for user input
Console.ReadKey();
}
}
}

  运行输出:

ProductB1 interacts with ProductA1
ProductB2 interacts with ProductA2
请按任意键继续. . .

4. 抽象工厂模式实践应用

  以KFC为例阐述抽象工厂模式的应用,假设现在KFC的食品直接没有任何关联,不可以分类,各个Product相互独立。这样工厂方法模式就可以很好解决,定义一系列的简单工厂,用户没要求一种食品就使用一个合适的简单工厂来生产相应的Product就可以。

  但实际情况下,KFC的产品还可以进行套餐出售,假设KFC的产品可以分为食品Food和饮料Drink,Food和Drink分别构成了一个产品族,一个产品族就是一系列相似对象的抽象。KFC出售2种套餐,一种是经济型,包括鸡翅和可乐;另一种是豪华型,包括鸡腿和咖啡。用户只需要指出需要的套餐名即可获得相应的Food和Drink。这种情况下,工厂方法模式将不再适用,而采用抽象工厂模式进行实现。

  KFCFood.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Practical
{
/// <summary>
/// Product族1,KFC食品
/// </summary>
public abstract class KFCFood
{
public abstract void Display();
}
}

  Chicken.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Practical
{
public class Chicken : KFCFood
{
public override void Display()
{
Console.WriteLine("鸡腿 + 1");
}
}
}

  Wings.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Practical
{
public class Wings : KFCFood
{
public override void Display()
{
Console.WriteLine("鸡翅 + 1");
}
}
}

  KFCDrink.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Practical
{
/// <summary>
/// Product族2,KFC饮料
/// </summary>
public abstract class KFCDrink
{
public abstract void Display();
}
}

  Coke.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Practical
{
public class Coke : KFCDrink
{
public override void Display()
{
Console.WriteLine("可乐 + 1");
}
}
}

  Coffee.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Practical
{
public class Coffee : KFCDrink
{
public override void Display()
{
Console.WriteLine("咖啡 + 1");
}
}
}

  IKFCFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Practical
{
/// <summary>
/// 抽象工厂,生产套餐
/// </summary>
public interface IKFCFactory
{
KFCFood CreateFood();
KFCDrink CreateDrink();
}
}

  CheapPackageFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Practical
{
/// <summary>
/// 经济型套餐,包括鸡翅和可乐
/// </summary>
public class CheapPackageFactory : IKFCFactory
{
public KFCFood CreateFood()
{
return new Wings();
}
public KFCDrink CreateDrink()
{
return new Coke();
}
}
}

  LuxuryPackageFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace DesignPatterns.AbstractFactoryPattern.Practical
{
/// <summary>
/// 豪华型套餐,包括鸡腿和咖啡
/// </summary>
public class LuxuryPackageFactory : IKFCFactory
{
public KFCFood CreateFood()
{
return new Chicken();
} public KFCDrink CreateDrink()
{
return new Coffee();
}
}
}

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using DesignPatterns.AbstractFactoryPattern.Practical; namespace DesignPatterns.AbstractFactoryPattern
{
class Program
{
static void Main(string[] args)
{
IKFCFactory factory = new CheapPackageFactory();
KFCFood food = factory.CreateFood();
food.Display(); KFCDrink drink = factory.CreateDrink();
drink.Display();
}
}
}

  运行输出:

鸡翅 + 1
可乐 + 1
请按任意键继续. . .

5. 抽象工厂模式应用分析

5.1 抽象工厂模式适用情形

  ◊ 同一个产品族的Product在一起使用时,而且它们之间是相互依赖的,不可分离

  ◊ 系统需要由相互关联的多个对象来构成

  ◊ 当想提供一组对象而不显示它们的实现过程,只显示它们的接口

  ◊ 系统不应当依赖一些具体Product类

5.2 抽象工厂模式的特点

  ◊ 隔离了具体类的生成,客户不需要知道怎样生成每一个具体Product,什么时间生成的。它将客户与具体的类分离,依赖于抽象类,耦合性低。

  ◊ 一个产品族中的多个对象设计成一起工作,它能保证客户端始终只使用一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说是非常实用的一种设计模式。

  ◊ 有利于更换产品系列,由于客户端只依赖于抽象类,更换产品系列时,只需要更改一下具体工厂名就可以。

  ◊ 难以支持新种类的产品,这是因为抽象工厂接口确定了可以被创建的产品集合,支持新种类的产品就需要扩展该工厂接口,这将引起抽象工厂类及其所有子类的改变。

5.3 抽象工厂模式与工厂方法模式区别

  ◊ 工厂方法模式只有一个抽象产品类,而抽象工厂模式可以有多个抽象产品类。

  ◊ 工厂方法模式针对一个产品等级结构,可以派生出多个具体产品类;抽象工厂模式针对面向多个产品等级结构,每个抽象产品类可以派生出多个具体产品类。

C#设计模式系列:抽象工厂模式(AbstractFactory)的更多相关文章

  1. Java设计模式系列-抽象工厂模式

    原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755412.html 一.概述 抽象工厂模式是对工厂方法模式的再升级,但是二者面对的场景稍显差别. ...

  2. 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)

    原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factor ...

  3. Java 设计模式之抽象工厂模式(三)

    原文地址:Java 设计模式之抽象工厂模式(三) 博客地址:http://www.extlight.com 一.前言 上篇文章 <Java 设计模式之工厂模式(二)>,介绍了简单工厂模式和 ...

  4. C#设计模式之四抽象工厂模式(AbstractFactory)【创建型】

    一.引言     写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了 ...

  5. C#设计模式之三抽象工厂模式(AbstractFactory)【创建型】

    一.引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了解决[简 ...

  6. Java设计模式系列之工厂模式

    工厂模式将大量有共同接口的类实例化,工厂模式可以实现动态决定实例化哪一个类的对象,工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factory):添加某一种类型的 ...

  7. C#设计模式(4)-抽象工厂模式

    引言 上一篇介绍了设计模式中的简单工厂模式-C#设计模式(3)-工厂方法模式,本篇将介绍抽象工厂模式: 抽象工厂模式简介 抽象工厂模式(AbstractFactory):提供一个创建一系列相关或相互依 ...

  8. Head First设计模式之抽象工厂模式

    一.定义 给客户端提供一个接口,可以创建多个产品族中的产品对象 ,而且使用抽象工厂模式还要满足一下条件:     1)系统中有多个产品族,而系统一次只可能消费其中一族产品.      2)同属于同一个 ...

  9. 【设计模式】抽象工厂模式 Abstract Factory Pattern

    简单工厂模式是一个工厂类根据工厂方法的参数创建不出不同的产品, 工厂方法模式是每一个产品都有一个一一对应的工厂负责创建该产品.那么今天要讲的抽象工厂模式是一个工厂能够产生关联的一系列产品.抽象工厂模式 ...

  10. Java 设计模式之抽象工厂模式

    抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂.该超级工厂又称为其他工厂的工厂.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在抽 ...

随机推荐

  1. Ubuntu 12.04下mysql的安装与配置

    转自:http://blog.csdn.net/ichsonx/article/details/9285935 准备  0. 获取 mysql-5.5.15-linux2.6-i686.tar.gz ...

  2. weblogic检查项

    日常维护中,weblogic检查的几个项: 1.JVM: 如最大堆内存.最小堆内存. 2.GC回收: 查看jvm空闲内存变化情况,每次GC的回收情况:控制台可以强制垃圾回收,看看回收内存是否太小,如果 ...

  3. pyQt绘图

    def paintEvent(self, e): qp = QtGui.QPainter() qp.begin(self) self.DrawChessBoard(qp) self.Draw_Ches ...

  4. jquery超炫的列表筛选插件

    今天要为大家带来一款非常实用的jquery列表筛选插件,效果非常好.单击某项的时候动画筛选该项的列表.我们一起看下效果图: 在线预览   源码下载 我们一起看下实现的代码: html代码: <d ...

  5. [sz,rz]使用sz/rz在两台Linux设备之间传输数据

    转自:https://superuser.com/questions/604055/using-rz-and-sz-under-linux-shell zsend #!/bin/sh DEV=/dev ...

  6. BusyBox getty

    linux的登录主要是由两个文件在控制,/usr/sbin/getty来获得用户名,并进行检查用户名是否存在,然后将用户名传递给/usr/bin/login来获取用户输入密码和检查密码是否正确. 所以 ...

  7. ubuntu 12.10 默认安装php5-fpm无监听9000端口,nginx无法链接php5-fpm修正

    升级php5的时候,发现nginx无法链接到php5,怀疑是php5端口的问题. netstat -an未发现监听9000端口. 查看/var/log/php5-fpm.log一切正常. 随后查看/e ...

  8. DataGridView使用技巧十二:DataGridView Error图标表示的设定

    为了提醒用户注意,DataGridView可以使用Error图标来突出显示. Error图标可以在单元格和行头内表示,但不能在列头上显示. 1.ErrorText属性 当设定单元格/行的ErrorTe ...

  9. mac配置完ssh依然提示"Enter passphrase for key"解决方法

    使用Git,每次都提示输入命令. 这个问题折磨很久,明明已经配置过ssh了,可是每次还要提示输入密码,从网上查查,最后一条命令解决问题: 问题提示: Enter passphrase for key ...

  10. ThinkPHP3.2 分组分模块

    ThinkPHP/Conf/convention.php 'CONTROLLER_LEVEL'      =>  1, 修改成 'CONTROLLER_LEVEL'      =>  2,