AbstractFactory抽象工厂模式(创建型模式)
1、new 的问题
常见的对象创建方法:
//创建一个Road对象 Road road=new Road();
new的问题:实现依赖,不能应对具体实例的变化
怎么理解上面这句话呢?
可以这样理解:我们创建的对象实例依赖于Road对象的内部实现,如果Road对象不会发生变化(或者发生变化的频率很小),那么单纯的用new是可以的,但是上面的Road我们单纯籽籽棉意思上理解,路肯定是变化很大的,路有水泥路,马路,公路等等,所以每当我们的Road发生变化,单纯用new的方式,我们就必须修改所有使用过Road的地方。
总结:所以可以得出一个结论,当我们new的业务对象变化比较频繁的时候,就不能使用new来创建对象;如果要创建的业务对象很稳定,不会发生平凡的变化,那么可以使用new.
2、如何解决new的问题呢?
解决new的问题,最好的方法就是封装变化点,哪里经常变化,就把那里封装起来
3、工厂模式源起
(1)、2中说了,要解决new的问题,就是封装变化点,而new的问题就是"对象创建的不定性",对象的频繁变化,所以我们就封装"对象的创建"。
(2)、这也引申出了另一个编程思想:面向接口编程---依赖接口,而非依赖实现
(3)、抽象工厂的简易版:
using System; namespace AF { class AbstractFactorySimple { static void Main(string[] args) { //创建一个Road对象 Road road = AbstractFactory.CreateRoad(); } } public class AbstractFactory { public static Road CreateRoad() { return new Road(); } } class Road { } }
4、假设有一个游戏开发场景:我们需要构造"道路"、"房屋"、"地道"、"丛林"等等对象,可以用下面的最浅层的工厂模式来封装
using System; namespace AF { class AbstractFactoryShallow { } public class AbstractFactory { public static Road CreateRoad() { return new Road(); } public static Jungle CreateJungle() { return new Jungle(); } public static Buliding CreateBuliding() { return new Buliding(); } public static Postern CreatePostern() { return new Postern(); } } class Road { } class Jungle { } class Buliding { } class Postern { } }
上面的代码是最浅层的封装,也就是简单的工厂,也称之为"静态工厂";解决了对象创建的不确定性;
5、这个时候需求又变了,接着第四个问题,一般游戏都会有不同的风格,所以"道路","暗道","丛林","房屋"也会有不同的风格,这个时候在解决对象创建的不确定之后,产生了对象的不决定性,也就是道路对象可能会有很多种,丛林也可能会有很多种,等等的问题,那么显然上面的简单工厂(静态工厂)并不能解决我们的问题;
在提出上面问题的解决方案之前,先说下动机:
在软件系统中,经常面临着"一系列相互依赖的对象创建",而随着业务需求的改变,往往存在更多系列对象的创建
解决方法:绕过常规的对象创建方法,提供一种"封装机制",来避免客户程序和多系列对象创建的紧耦合。
,如果不理解前面的概念,可以4中的分析;
6、抽象工厂的意图
提供一个接口,让接口负责创建一系列"相关或者相互依赖"的对象,无须指定具体的类。
7、结构图
8、完整工厂代码
using System; namespace AF { //抽象工厂层 public abstract class Road { public abstract void AAA(Jungle jungle); } public abstract class Jungle { public abstract void BBB(); } public abstract class Building { public abstract void CCC(); } public abstract class Tunnel { public abstract void DDD(); } public abstract class AbstractFactory { public abstract Road CreateRoad(); public abstract Jungle CreateJungle(); public abstract Building CreateBuilding(); public abstract Tunnel CreateTunnel(); } //抽象工厂层 //现代工厂层 public class ModernRoad :Road { public override void AAA(Jungle jungle) { } } public class ModernJungle : Jungle { public override void BBB() { } } public class ModernBuilding : Building { public override void CCC() { throw new NotImplementedException(); } } public class ModernTunnel : Tunnel { public override void DDD() { throw new NotImplementedException(); } } public class ModernFactory : AbstractFactory { public override Road CreateRoad() { return new ModernRoad(); } public override Jungle CreateJungle() { return new ModernJungle(); } public override Building CreateBuilding() { return new ModernBuilding(); } public override Tunnel CreateTunnel() { return new ModernTunnel(); } } //现代工厂层结束 //古典工厂层 public class ClassicalRoad : Road { public override void AAA(Jungle jungle) { } } public class ClassicalJungle : Jungle { public override void BBB() { } } public class ClassicalBuiliding : Building { public override void CCC() { } } public class ClassicalTunnel : Tunnel { public override void DDD() { } } public class ClassicalFactory : AbstractFactory { public override Road CreateRoad() { return new ClassicalRoad(); } public override Jungle CreateJungle() { return new ClassicalJungle(); } public override Building CreateBuilding() { return new ClassicalBuiliding(); } public override Tunnel CreateTunnel() { return new ClassicalTunnel(); } } //古典工厂层结束 //客户端,客户端只依赖于抽象类个抽象方法,不依赖具体实现,这样客户端就很稳定 public class GameManager { Road road; Building building; Tunnel tunnel; Jungle jungle; AbstractFactory factory; public GameManager(AbstractFactory factory) { this.factory = factory; } public void BulidFacilities() { road = factory.CreateRoad(); tunnel = factory.CreateTunnel(); jungle = factory.CreateJungle(); building = factory.CreateBuilding(); } public void Run() { road.AAA(jungle); tunnel.DDD(); building.CCC(); jungle.BBB(); } } public class APP { static void Mains() { GameManager game = new GameManager(new ModernFactory()); game.Run(); } } }