主程序
namespace _2.AbstractFactory
{
class Program
{
static void Main(string[] args)
{
Patrix patrix = new Patrix();
patrix.LoadScene("HalfPaper");
patrix.LoadScene("Matrix");
Console.ReadKey();
}
}
}
Patrix类
using System.Reflection;
class Patrix
{
private PatrixSceneFactory GetGameScene(string gameSceneName)
{
return (PatrixSceneFactory)Assembly.Load("2.AbstractFactory").CreateInstance("_2.AbstractFactory." + gameSceneName);
}
public void LoadScene(string gameSceneName)
{
PatrixSceneFactory psf = GetGameScene(gameSceneName);
Texture texture = psf.CreateTexture();
Model model = psf.CreateModel();
model.FillTexture(texture);
}
}
PatrixSceneFactory类
abstract class PatrixSceneFactory
{
public abstract Model CreateModel();
public abstract Texture CreateTexture();
}
Model类
abstract class Model
{
public abstract void FillTexture(Texture texture);
}
Texture类
abstract class Texture
{
}
HalfPaper类
class HalfPaper:PatrixSceneFactory
{
public override Model CreateModel()
{
return new HalfPaperModel();
}
public override Texture CreateTexture()
{
return new HalfPaperTexture();
}
}
class HalfPaperModel:Model
{
public HalfPaperModel()
{
Console.WriteLine("HalfPaper Model Created");
}
public override void FillTexture(Texture texture)
{
Console.WriteLine("HalfPaper Model is filled Texture");
}
}
class HalfPaperTexture : Texture
{
public HalfPaperTexture()
{
Console.WriteLine("HalfPaper Texture Created");
}
}
Matrix类
class Matrix : PatrixSceneFactory
{
public override Model CreateModel()
{
return new MatrixModel();
}
public override Texture CreateTexture()
{
return new MatrixTexture();
}
}
class MatrixModel : Model
{
public MatrixModel()
{
Console.WriteLine("Matrix Model Created");
}
public override void FillTexture(Texture texture)
{
Console.WriteLine("Matrix Model is filled Texture");
}
}
class MatrixTexture:Texture
{
public MatrixTexture()
{
Console.WriteLine("Matrix Texture Created");
}
}
意图
- 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
场景
- 还是上次说的那个网络游戏,定下来是一个休闲的FPS游戏。和CS差不多,8到16个玩家在游戏里面分成2组对战射击。
现在要实现初始化场景的工作。要呈现一个三维物体一般两个元素是少不了的,一是这个物体的骨架,也就是模型,二就是这个骨架上填充的纹理。
我们知道,这样的一个游戏不可能只有一张地图,而且地图的数量肯定是会一直增加的。
如果游戏在初始化场景的时候需要根据不同的地图分别加载模型和纹理对象, 那么势必就会使得场景的扩充变得很不方便。
由此,我们引入AbstractFactory,抽象工厂生产的都是实际类型的接口(或者抽象类型) ,如果加了新的场景可以确保不需要修改加载场景的那部分代码。
代码说明
- PatrixSceneFactory就是一个抽象工厂,它声明了创建抽象的场景以及抽象的纹理的接口。
- Model和Texture是抽象产品。 在Model类中有一个抽象方法, 用于为模型填充纹理。
- HalfPaper和Matrix是具体工厂,它用于创建某个场景的模型和纹理。 (你可能对两个类的名字不太理解,其实HalfPaper和Matrix是两个地图的名字)
- xxxModel 和 xxxTexture 就是具体的产品了。它们就是针对某个场景的模型和纹理,具体工厂负责创建它们。
- Patrix 这个类负责加载场景,为了避免加载不同场景使用 case语句,在这里我们使用反射来加载具体工厂类。
- 可以看到,一旦有了新的场景(或者说地图) ,我们只需要设计新的 xxxModel 和xxxTexture以及具体工厂类就可以了,加载场景的那部分代码(也就是 Patrix 类)不需要做改动。
- 我们现在这个游戏可是不支持和电脑对战的,万一以后需要支持电脑了,那么场景中的元素除了纹理和模型之外就还需要加电脑了。
也就是说抽象工厂还需要多生产一种类型的产品,这个时候抽象工厂就无能为力了。
抽象工厂只能解决系列产品扩张的变化点(在我们的例子中就是地图的新增) ,因此千万把抽象工厂所能生产的产品考虑周全了。
何时采用
- 从代码角度来说,你希望在统一的地方创建一系列相互关联的对象,并且基于抽象对象的时候。
- 从应用角度来说,如果你的产品是成组成套的,并且肯定会不断扩展新系列的,那么就适用抽象工厂。
比如说,外面买的塑料模型,里面总是有图纸、模型元件板和外壳包装三部分。那么生产模型的厂就是抽象工厂,打印图纸、打印包装盒以及生产元件板的三个流水线就是具体工厂了。需要生产新的模型,只需要制作新的图纸输入到三个流水线的电脑中就可以了。
实现要点
- 抽象工厂本身不负责创建产品, 产品最终还是由具体工厂来创建的。 比如, MatrixModel是Matrix创建的, 而不是PatrixSceneFactory创建的。
在.NET中可以使用反射来创建具体工厂,从而使得代码变动降到最低。 - 在抽象工厂中需要体现出生产一系列产品。这一系列产品是相互关联,相互依赖一起使用的。
- 抽象工厂对应抽象产品,具体工厂对应具体产品,外部依赖抽象类型,这样对于新系列产品的创建,外部唯一依赖的就是具体工厂的创建过程(可以通过反射解决) 。
注意事项
- 一般来说需要创建一系列对象的时候才考虑抽象工厂。比如,创建一个场景,需要创建模型和纹理,并且模型和纹理之间是有一定联系的,不太可能把 PatrixTexture套用在MatrixModel上。
- 如果系统的变化点不在新系列的扩充上,那么就没有必要使用抽象工厂。比如,如果我们不会增加新地图的话,那么也就没有必要引入抽象工厂。
C#设计模式一:Singleton(含实例源码)
C#设计模式二:AbstractFactory(含实例源码)
C#设计模式三:FactoryMethod(含实例源码)
C#设计模式四:Prototype(含实例源码)
C#设计模式五:Builder(含实例源码)
C#设计模式六:Adapter(含实例源码)
C#设计模式七:Facade(含实例源码)
C#设计模式八:Proxy(含实例源码)
C#设计模式九:Flyweight(含实例源码)
C#设计模式十:Composite(含实例源码)
C#设计模式十一:Bridge(含实例源码)
网友评论