C#设计模式系列:抽象工厂模式(AbstractFactory)
出自: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)的更多相关文章
- Java设计模式系列-抽象工厂模式
原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755412.html 一.概述 抽象工厂模式是对工厂方法模式的再升级,但是二者面对的场景稍显差别. ...
- 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)
原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factor ...
- Java 设计模式之抽象工厂模式(三)
原文地址:Java 设计模式之抽象工厂模式(三) 博客地址:http://www.extlight.com 一.前言 上篇文章 <Java 设计模式之工厂模式(二)>,介绍了简单工厂模式和 ...
- C#设计模式之四抽象工厂模式(AbstractFactory)【创建型】
一.引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了 ...
- C#设计模式之三抽象工厂模式(AbstractFactory)【创建型】
一.引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了解决[简 ...
- Java设计模式系列之工厂模式
工厂模式将大量有共同接口的类实例化,工厂模式可以实现动态决定实例化哪一个类的对象,工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factory):添加某一种类型的 ...
- C#设计模式(4)-抽象工厂模式
引言 上一篇介绍了设计模式中的简单工厂模式-C#设计模式(3)-工厂方法模式,本篇将介绍抽象工厂模式: 抽象工厂模式简介 抽象工厂模式(AbstractFactory):提供一个创建一系列相关或相互依 ...
- Head First设计模式之抽象工厂模式
一.定义 给客户端提供一个接口,可以创建多个产品族中的产品对象 ,而且使用抽象工厂模式还要满足一下条件: 1)系统中有多个产品族,而系统一次只可能消费其中一族产品. 2)同属于同一个 ...
- 【设计模式】抽象工厂模式 Abstract Factory Pattern
简单工厂模式是一个工厂类根据工厂方法的参数创建不出不同的产品, 工厂方法模式是每一个产品都有一个一一对应的工厂负责创建该产品.那么今天要讲的抽象工厂模式是一个工厂能够产生关联的一系列产品.抽象工厂模式 ...
- Java 设计模式之抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂.该超级工厂又称为其他工厂的工厂.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在抽 ...
随机推荐
- 【转】Update: Android.mk 中的 LOCAL_SRC_FILES, LOCAL_C_INCLUDES
看原文请移步:Update: Android.mk 中的 LOCAL_SRC_FILES, LOCAL_C_INCLUDES 我在先前的两篇post 编写Android.mk中的LOCAL_SRC_F ...
- 关于Parse字符串为时间一次被坑经历
在Java代码中发现一个bug,就是本来更新为时间的内容更新为一些奇怪的内容,比如20819这种形式,本来更新的时间都是近期不会超过一年, 为什么会出现这种情况,非常奇怪,遂调试下代码,跟踪发现要匹配 ...
- NIS & Kerberos配置
NIS & Kerberos配置 所需RPM包列表: krb5-server-1.10.3-42.el6.x86_64.rpm krb5-workstation-1.10.3-42.el6.x ...
- Android开发:keytool' 不是内部或外部命令 也不是可运行的程序
今天在更改keystore密码的时候,发生了这个问题:keytool' 不是内部或外部命令 也不是可运行的程序. 本来以为很简单觉得的问题,在网上搜索了一大堆答案,都不是我想要的,故在此记录下我的解决 ...
- C#类的修饰符
## C#类的修饰符------------------------- public 任何地方可以调用- internal 同一应用程序集内使用- partial 部分类,一个类分成几部分写在不同文件 ...
- 使用conda 对gcc进行升级 (sonicparanoid)
由于要是用python 3.6版本的一个包sonicparanoid,但是系统的gcc比较老,所以先用conda创建python环境,在该环境下尽心gcc的安装和升级 conda create --n ...
- jacky自问自答-数据库
1.exists和in有什么区别? EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False,而In子查询则是返回具体的数据值,与指定的字段比较 ...
- dubbo2.5.3注解版
1.环境 在机器192.168.0.4机器上安装了zookeeper,用于dubbo的服务注册,安装教程在另外一篇博客 http://www.cnblogs.com/520playboy/p ...
- am335x gpio 模拟 spi 驱动添加
kernel 内 make menuconfig // make menuconfig Device Drivers ---> [*] SPI support ---> <*> ...
- FusionCharts JavaScript API - Events 全局事件处理
FusionCharts JavaScript API - Events 全局事件处理 Home > FusionCharts XT and JavaScript > API Refere ...