











抽象工厂模式(Abstract Factory Pattern)
引入:
在前面介绍的两个创建型模式里面,我们解决的都是有关"new"的问题,用它们来避免显式指定类创建对象。我写的也非常简单易懂,相信看过的朋友们都应该对简单工厂模式、工厂方法模式的意图、所能解决的问题及适用情景有一定的了解了。但是若要达到灵活运用,什么时候用,怎样用合适还不是看一篇文章就能解决的问题。呵呵..这需要你对OO的理解程度,你的项目开发经验等等许多方面的积累。一起努力喔。。
意图:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
参考者:
也就是该模式中的各个类或对象之间的关系:
抽象工厂模式UML图

抽象工厂模式在生活中的实例
咱们继续拿怎么穿衣服来说明这个抽象工厂模式。
就拿你来说吧。工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。咱们假设一种情况(现实中是不存在的,要不然,没法进入共产主义了,但有利于说明抽象工厂模式),在你的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用OO的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
分析:
要好好去读上面那个实例,虽然有点绕嘴,其实只要用心去读,分清了抽象工厂模式的各个角色,对理解设计模式是非常重要的。理解头绪,然后接合
具体代码如下:
抽象工厂角色:
1
namespace AbstractFactory
2
{
3
//抽象工厂类,
4
public abstract class AbstractClothes
5
{
6
//抽象方法:创建一个上衣
7
abstract public AbstractCoat CreateCoat();
8
//抽象方法:创建一个裤子
9
abstract public AbstractTrousers CreateTrousers();
10
}
11
}
12
抽象产品角色:
1
namespace AbstractFactory
2
{
3
/// <summary>
4
/// 抽象产品----上衣抽象类
5
/// </summary>
6
public abstract class AbstractCoat
7
{
8
//性别属性
9
public abstract bool Sex
10
{
11
get;
12
}
13
14
//样式属性
15
public abstract string Style
16
{
17
get;
18
}
19
}
20
21
/// <summary>
22
/// 抽象产品----裤子抽象类
23
/// </summary>
24
public abstract class AbstractTrousers
25
{
26
//性别属性
27
public abstract bool Sex
28
{
29
get;
30
}
31
32
//样式属性
33
public abstract string Style
34
{
35
get;
36
}
37
}
38
}
39
具体工厂角色:
1
namespace AbstractFactory
2
{
3
/// <summary>
4
///时尚男装
5
/// </summary>
6
public class FashionManClothes:AbstractClothes
7
{
8
public override AbstractFactory.AbstractCoat CreateCoat()
9
{
10
return new CoatA();
11
}
12
13
public override AbstractTrousers CreateTrousers()
14
{
15
return new TrousersA();
16
}
17
}
18
19
/// <summary>
20
/// 时尚女装
21
/// </summary>
22
public class FashionWomanClothes : AbstractClothes
23
{
24
public override AbstractCoat CreateCoat()
25
{
26
return new CoatB();
27
//throw new Exception("The method or operation is not implemented.");
28
}
29
public override AbstractTrousers CreateTrousers()
30
{
31
return new TrousersB();
32
//throw new Exception("The method or operation is not implemented.");
33
}
34
}
35
}
具体产品角色:(注意:我并没有把所有的具体产品类都列出来,由于简单,可以推想出剩余的产品类,详见附件)
1
namespace AbstractFactory
2
{
3
/// <summary>
4
/// 时尚男性上衣
5
/// </summary>
6
public class CoatA:AbstractFactory.AbstractCoat
7
{
8
private bool sex = true;
9
private string style = "时尚";
10
/// <summary>
11
/// 重写基类的Sex属性
12
/// </summary>
13
public override bool Sex
14
{
15
get
16
{
17
return sex;
18
}
19
}
20
21
/// <summary>
22
/// 重写基类的Style属性
23
/// </summary>
24
public override string Style
25
{
26
get
27
{
28
return style;
29
}
30
}
31
}
32
33
/// <summary>
34
/// 时尚男性裤子
35
/// </summary>
36
public class TrousersA : AbstractTrousers
37
{
38
private bool sex = true;
39
private string style = "时尚";
40
public override bool Sex
41
{
42
get
43
{
44
return sex;
45
}
46
}
47
public override string Style
48
{
49
get
50
{
51
return style;
52
}
53
}
54
}
55
}
客户端代码:
1
namespace AbstractFactory
2
{
3
/// <summary>
4
/// 创建衣服类
5
/// </summary>
6
public class CreateClothes
7
{
8
private AbstractCoat myCoat;
9
private AbstractTrousers myTrousers;
10
public CreateClothes(AbstractClothes clothes)
11
{
12
myCoat = clothes.CreateCoat();
13
myTrousers = clothes.CreateTrousers();
14
}
15
16
public void ShowMyClothes()
17
{
18
Console.WriteLine("My Clothes:");
19
string sex= myCoat.Sex ? "男" : "女";
20
//Console.WriteLine("Coat:{0} {1}", myCoat.Sex ? "男" : "女", myCoat.Style);
21
Console.WriteLine("Coat:{0} {1}", sex, myCoat.Style);
22
sex=myTrousers.Sex?"男":"女";
23
Console.WriteLine("Trousers:{0} {1}", sex, myTrousers.Style);
24
}
25
}
26
27
28
public class Client
29
{
30
static void Main(string[] args)
31
{
32
//创建一个工厂类的实例
33
string assemblyName = ConfigurationManager.AppSettings["assemblyName"];
34
string fullTypeName =string.Concat( ConfigurationManager.AppSettings["nameSpaceName"] ,".", ConfigurationManager.AppSettings["typename"]);
35
36
AbstractClothes factory = (AbstractClothes)Assembly.Load(assemblyName).CreateInstance(fullTypeName);
37
CreateClothes clothes = new CreateClothes(factory);
38
clothes.ShowMyClothes();
39
Console.Read();
40
}
41
}
42
}
43
app.config文件
1
<configuration>
2
<appSettings>
3
<!--一般情况下只需改第三个"typename"就行了,具体工厂类 -->
4
<add key="assemblyName" value="ConcreteFactory"/>
5
<add key="nameSpaceName" value="AbstractFactory"/>
6
<add key="typename" value="FashionManClothes"/>
7
</appSettings>
8
</configuration>
这样,代码就完成了。
小结一下:
抽象工厂模式堪称gof23种设计模式精典模式之一,它能够解决诸如:
通过显示指定类创建对象,紧耦合,对对象表示或实现的依赖等等一些问题,有关设计模式的设计原则,所能解决的问题,详见OO与设计模式的原则、目标 。
抽象工厂模式适用于对“一系列相互依赖的对象”的创建工作,这些对象是相互依赖的,是有联系的。如果仅为一个对象的创建则用简单工厂模式或工厂方法模式完全可以实现,没有必要用抽象工厂模式。
由于抽象工厂模式的客户端只依赖于抽象工厂,抽象产品,在初始化过程中仅用到一次具体工厂我们又把它放在了app.config中了,完全依赖接口,这样不仅在系统的扩展性方面好,而且可以提高团队开发效率。两个团队只要彼此了解定义的接口,抽象类,可以并行开发。举个例子,就拿博客园来说吧,我们在用自己的博客空间时,可以随时的换皮肤,这个换皮肤是不是典型的抽象工厂模式吗?如果是,它的各个角色又是什么呢?我认为是的。换一下皮肤,你博客页面上的各个样式都变了,而且这里各个样式都同属于你选定的这一个皮肤。而每个样式都又是独立的,它们组合起来就成了一款皮肤。我们来揪出来各个角色。
抽象工厂:皮肤
抽象产品:样式
具体工厂:某一款皮肤,皮肤名即为具体工厂的类名
具体产品:某一个样式。
虽然不存在这样的接口与类,但是它确实是抽象工厂模式的一个应用。抽象工厂制定都有哪些样式名,而具体工厂来实现这些样式名中的样式,而具体工厂中用到的各个样式都是一个具体产品。这也是我的理解,如兄弟们有不同的见解,欢迎发表意见,共同探讨。
确定过各个角色之后,就可以说一下为什么提高效率了。不论dudu在设计博客园时用什么工具或语言,它与泸江博客只要约定好所有用到的样式名就可以了。而泸江博客就可以根据要求单独去做每一款皮肤了。
优点:
缺点:
应用情景:
应用场景举例:
源程序下载:AbstractFactory.rar
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。