转自这里 http://www.unitymanual.com/thread-38023-1-1.html
话说野猪上次讲到了工厂家族里面的工厂方法模式的修炼心法,不知各位侠士是否已经了然于胸了呢?如果没有,还需再修行呀!今天咱们就要开启工厂家族里面的最后一个模式—抽象工厂模式。在修炼抽象工厂模式心法之前,我先说个例子,大家都应该知道武学至宝-葵花宝典吧。想必你可能知道欲练此功必先自宫,哈哈!或许你看到的只是他的上半部,但当你看到下半部结尾一行醒目的文字-欲练此功也可不必自宫,此刻傻眼了吧!失去了独领风骚的快感。由此例子,来引出产品族的概念。葵花宝典的上、下部产生了相互影响就可以认为是一个产品族。所谓产品族,是指位于不同产品等级结构,功能相关联的产品组成的家族。由产品族,我们来进入抽象工厂模式。抽象工厂模式是工厂方法的升级版,是所有形态的工厂模式中最为抽象和最具一般性的形态。而所谓的抽象工厂是一个工厂等级结构可以创建分属于不同产品等级结构的一个产品族中的所有对象。说了那么多了,让我们开始修炼抽象工厂模式的心法吧。
修炼抽象工厂模式的心法如下:
1)抽象工厂角色AbstractFactory:此角色是工厂方法模式的核心,与系统业务逻辑无关。
2)具体工厂角色ConcreteFactory:此角色在客户端的调用下创建产品的实例。他包含有选择合适产品对象的逻辑,而这个逻辑是与应用系统的业务逻辑紧密相关。
3)抽象产品角色AbstractProduct:担任这个角色的类是工厂方法模式所创建对象的父类或他们共同拥有的接口。
4) 具体产品角色ConcreteProduct:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,里面包含了应用系统的业务逻辑。
修炼抽象工厂模式的武功套路如下:
(备注:上面是抽象工厂模式demo里面的定向关系图文档的截图!)
修炼心法与武功套路的对应:
1) 抽象工厂角色AbstractFactory对应武功套路里面的ResourceAbstractFactory。
2) 具体工厂角色ConcreteFactory对应武功套路里面的PrimaryManagerFactory和AssistantManagerFactory。
3) 抽象产品角色AbstractProduct对应武功套路里面的UIResourceAbstract和AudioResourceAbstract。
4) 具体产品角色ConcreteProduct对应武功套路里面的PrimaryUIManager和PrimaryAudioManager、AssistantUIManager和AssistantAudioManager。
上面描述了抽象工厂模式的修炼心法和武功套路。下面就给出具体的套路细节。
建议:看下面代码之前,可以先根据抽象工厂模式的心法及对应的武功套路先行修炼。
抽象工厂角色:
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
using
UnityEngine;
using
System.Collections;
namespace
AbstractFactory
{
/// <summary>
/// 定义抽象工厂
/// </summary>
public
abstract
class
ResourceAbstractFactory
{
public
abstract
UIResourceAbstract CreateUIManager();
public
abstract
AudioResoucesAbstract CreateAudioManager();
}
}
|
具体工厂角色:
产品族一:PrimaryManagerFactory工厂
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
namespace
AbstractFactory
{
/// <summary>
/// 定义抽象工厂的具体产品工厂PrimaryManagerFactory
/// </summary>
public
class
PrimaryManagerFactory : ResourceAbstractFactory
{
public
override
UIResourceAbstract CreateUIManager()
{
return
new
PrimaryUIManager();
}
public
override
AudioResoucesAbstract CreateAudioManager()
{
return
new
PrimaryAudioManager();
}
}
|
}
产品族二:AssistantManagerFactory工厂
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
using
UnityEngine;
using
System.Collections;
namespace
AbstractFactory
{
/// <summary>
///定义抽象工厂的具体工厂AssistantManagerFactory
/// </summary>
public
class
AssistantManagerFactory : ResourceAbstractFactory
{
public
override
UIResourceAbstract CreateUIManager()
{
return
new
AssistantUIManager();
}
public
override
AudioResoucesAbstract CreateAudioManager()
{
return
new
AssistantAudioManager();
}
}
}
|
抽象产品角色:
音频资源抽象产品
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
using
UnityEngine;
using
System.Collections;
namespace
AbstractFactory
{
/// <summary>
/// 定义音乐资源抽象类
/// </summary>
public
abstract
class
AudioResoucesAbstract
{
public
abstract
void
LoadConfig(
string
path);
public
abstract
void
LoadAsset(
string
name);
public
abstract
void
UnLoadResource(
bool
status);
}
}
|
UI资源抽象产品
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
using
UnityEngine;
using
System.Collections;
namespace
AbstractFactory
{
/// <summary>
/// 定义UI资源的抽象类
/// </summary>
public
abstract
class
UIResourceAbstract
{
public
abstract
void
LoadConfig(
string
path);
public
abstract
void
LoadAsset(
string
name);
public
abstract
void
UnLoadResource(
bool
status);
}
}
|
具体产品角色:
产品族一:
PrimaryUIManager具体产品
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
using
UnityEngine;
using
System.Collections;
namespace
AbstractFactory
{
/// <summary>
/// 定义UI抽象类的具体产品PrimaryUIManager
/// </summary>
public
class
PrimaryUIManager : UIResourceAbstract
{
public
override
void
LoadConfig(
string
path)
{
Debug.Log(
"PrimaryUIManager: "
+path);
}
public
override
void
LoadAsset(
string
name)
{
Debug.Log(
"PrimaryUIManager: "
+name);
}
public
override
void
UnLoadResource(
bool
status)
{
Debug.Log(
"PrimaryUIManager: "
+status);
}
}
}
|
PrimaryAudioManager具体产品
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
using
UnityEngine;
using
System.Collections;
namespace
AbstractFactory
{
/// <summary>
/// 定义Audio抽象类的具体产品PrimaryAudioManager
/// </summary>
public
class
PrimaryAudioManager : AudioResoucesAbstract
{
public
override
void
LoadConfig(
string
path)
{
Debug.Log(
"PrimaryAudioManager:"
+path);
}
public
override
void
LoadAsset(
string
name)
{
Debug.Log(
"PrimaryAudioManager: "
+name);
}
public
override
void
UnLoadResource(
bool
status)
{
Debug.Log(
"PrimaryAudioManager: "
+status);
}
}
}
|
产品族二:
AssistantUIManager具体产品
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
using
UnityEngine;
using
System.Collections;
namespace
AbstractFactory
{
/// <summary>
/// 抽象产品的具体产品AssignmentUIManager
/// </summary>
public
class
AssistantUIManager : UIResourceAbstract
{
public
override
void
LoadConfig(
string
path)
{
Debug.Log(
"AssistantUIManager:"
+path);
}
public
override
void
LoadAsset(
string
name)
{
Debug.Log(
"AssistantUIManager:"
+name);
}
public
override
void
UnLoadResource(
bool
status)
{
Debug.Log(
"AssistantUIManager:"
+status);
}
}
}
|
AssistantAudioManager具体产品
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
using
UnityEngine;
using
System.Collections;
namespace
AbstractFactory
{
/// <summary>
/// 抽象产品的具体产品AssistantAudioManager
/// </summary>
public
class
AssistantAudioManager : AudioResoucesAbstract
{
public
override
void
LoadConfig(
string
path)
{
Debug.Log(
"AssistantAudioManager: "
+path);
}
public
override
void
LoadAsset(
string
name)
{
Debug.Log(
"AssistantAudioManager: "
+name);
}
public
override
void
UnLoadResource(
bool
status)
{
Debug.Log(
"AssistantAudioManager: "
+status);
}
}
}
|
客户端测试类:
[C#]
纯文本查看
复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
using
UnityEngine;
using
System.Collections;
namespace
AbstractFactory
{
public
class
ResourceAbstractFactoryClient : MonoBehaviour
{
ResourceAbstractFactory rfPrimary;
AudioResoucesAbstract audioPrimry;
UIResourceAbstract uiPrimary;
ResourceAbstractFactory rfAssistant;
AudioResoucesAbstract audioAssistant;
UIResourceAbstract uiAssistant;
void
Start()
{
rfPrimary =
new
PrimaryManagerFactory();
rfAssistant =
new
AssistantManagerFactory();
}
void
OnGUI()
{
if
(GUILayout.Button(
"主城产品族"
))
{
audioPrimry = rfPrimary.CreateAudioManager();
audioPrimry.LoadConfig(
"http:..."
);
audioPrimry.LoadAsset(
"蛮牛"
);
audioPrimry.UnLoadResource(
false
);
uiPrimary = rfPrimary.CreateUIManager();
uiPrimary.LoadConfig(
"http:..."
);
uiPrimary.LoadAsset(
"蛮牛"
);
uiPrimary.UnLoadResource(
false
);
}
if
(GUILayout.Button(
"副城产品族"
))
{
audioAssistant = rfAssistant.CreateAudioManager();
audioAssistant.LoadConfig(
"http:..."
);
audioAssistant.LoadAsset(
"蛮牛"
);
audioAssistant.UnLoadResource(
false
);
uiAssistant = rfAssistant.CreateUIManager();
uiAssistant.LoadConfig(
"http:..."
);
uiAssistant.LoadAsset(
"蛮牛"
);
uiAssistant.UnLoadResource(
false
);
}
}
}
}
|
搞懂了上面的武功心法和武功套路,你也就领悟了抽象工厂模式。正如野猪一直强调的一样,每种武功都有他的优缺点和解决 问题 的侧重点。So,come on,请往下看:
抽象工厂模式的优点:
1) 分离了具体的类,一个工厂封装创建产品对象的责任和过程,将客户端与类的实现分离。有利于产品系列的交换。只需改变具体的工程就可以使用不同的产品配置。
2) 有利于产品的一致性,当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象。
3) 良好的封装性,每个产品的实现类不是高层模块要关心的。更好的遵循了依赖倒置(DIP)的原则。
抽象工厂模式的缺点:
抽象工厂最大的缺点就是产品族扩展非常困难。难以支持新的产品等级结构,如果要支持新的产品等级结构就要扩展抽象工厂接口。这样就涉及到抽象工厂类及所有具体工厂子类的改变,违背了“开放-封闭(OCP)”的原则。
在这里野猪先给大家提一个醒,GoF23设计模式里面的每种模式都是针对某类特定问题的解决策略。So,没有什么设计模式是完美的!
Tips: 抽象工厂还可以配合.Net 里面的反射技术来去除Switch或If,解除分支判断带来的耦合。同时还可以借助依赖注入(DI)或者专门的IOC来帮助我们克服抽象工厂模式的先天不足。例子大家可以自行搜索查看,或者看 U3D 专用的IOC 框架,例如Strange IOC框架(注:在Unity 官方商店有free download),简单提下,此框架支持web,mobile平台,同时他还有MVC部分扩展,所有的都是针对u3d的哦,可以学习下。