【C#面向对象设计模式】03. Abstract Factory 抽象工厂(创建型模式)
一、new的问题
- 常规的对象创建方法:
//创建一个Road对象
Road road = new Road();
- new的问题:
- 实现依赖,不能应对“具体实例化类型”的变化。(路变成水泥路,代码就要同样发生变化)
- 解决思路:
- 封装变化点——哪里变化,封装哪里。
- 潜台词:如果没有变化,当然也不需要额外的封装。
二、工厂模式的缘起
- 变化点在“对象创建”,因此就封装“对象创建”
- 面向接口编程——依赖接口,而非依赖实现(实现松耦合)
- 最简单的解决方法:
class RoadFactory//类库
{
public static Road CreateRoad()
{
return new Road();//if change——》return new WaterRoad();下面也不用改,这样以后对所有路的变化都封装在了这里。
}
}
//——————————————————————————————————————————————
//创建一个road对象
Road road = RoadFactory.CreateRoad();//客户程序
三、创建一系列相互依赖的对象
- 假设一个游戏开发场景:我们需要构造“道路”、“房屋”、“地道”、“从林”……等等的对象
class RoadFactory_Game
{
//需求变化时的变化点
public static Road CreateRoad()
{
return new Road();
}
public static Building CreateBuilding()
{
return new Building();
}
public static Tunnel CreateTunnel()
{
return new Tunnel();
}
public static Jungle CreateJunnel()
{
return new Jungle();
}
}
//————————————————————————————————————————————————————
//相对稳定
Road road = RoadFactory_Game.CreateRoad();
Building building = RoadFactory_Game.CreateBuilding();
四、简单工厂的问题
-
问题:
- 不能应对“不同系列对象”的变化。比如有不同风格的游戏场景——对应不同风格的道路、房屋、地道……
-
如何解决:
- 使用面向对象的技术“封装”变化点。
五、动机
-
在软件系统中,经常面临着**“一系列相互依赖的对象”**的创建工作;同时,由于需求的变化,往往存在更多系列对象的创建工作。
-
如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种”多系列具体对象创建工作“的紧耦合?
六、意图
- 提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。
七、结构
八、游戏框架中的Abstract Factory应用
abstract class FacilitiesFactory
{
public abstract Road CreateRoad();
public abstract Building CreateBuilding();
public abstract Tunnel CreateTunnel();
public abstract Jungle CreateJungle();
}
public abstract class Building
{
}
public abstract class Tunnel
{
}
public abstract class Jungle
{
}
public abstract class Road
{
}
//客户程序
class GameManager
{
FacilitiesFactory FacilitiesFactory;
public GameManager(FacilitiesFactory facilitiesFactory)
{
this.FacilitiesFactory = facilitiesFactory;
}
public void BuildGameFacilities()
{
Road road = FacilitiesFactory.CreateRoad();
Building building = FacilitiesFactory.CreateBuilding();
Tunnel tunnel = FacilitiesFactory.CreateTunnel();
Jungle jungle = FacilitiesFactory.CreateJungle();
}
public class MordenBuilding:Building
{
}
public class MordenTunnel:Tunnel
{
}
public class MordenJungle:Jungle
{
}
public class MordenRoad:Road
{
}
public class MordenFacilitiesFactory:FacilitiesFactory
{
public override Road CreateRoad()
{
return new MordenRoad();
}
public override Building CreateBuilding()
{
return new MordenBuilding();
}
public override Tunnel CreateTunnel()
{
return new MordenTunnel();
}
public override Jungle CreateJungle()
{
return new MordenJungle();
}
}
public void Play()
{
road.AAA();
building.BB(road);
tunnel.CCC();
jungle.DDD(tunnel);
}
}
class App
{
public static void Main(string[] args)
{
GameManager g = new GameManager(new MordenFacilitiesFactory);
g.BuildGameFacilities();
g.Run();
}
}
九、Abstract Factory模式的几个要点
- 如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的静态工厂完全可以。(而不是对象的变化增减)
- “系列对象”指的是这些对象之间有相互依赖、或作用的关系,例如游戏开发场景中的“道路”与“房屋”的依赖,“道路”与“地道”的依赖。
- Abstract Factory模式主要在于应对“新系列”的需求变动。其缺点在于难以应对“新对象”的需求变动。
- Abstract Factory模式经常和Factory Method模式共同组合来应对“对象创建”的需求变化。