设计模式-抽象工厂
简单工厂模式:https://www.cnblogs.com/Kyle-Wang/p/16063512.html
工厂模式:https://www.cnblogs.com/Kyle-Wang/p/16095863.html
一、抽象工厂的引入
在工厂模式里或者简单工厂模式里,我们的工厂都只负责创建种族(IRace),但其实在很多情况下,工厂并不只是创建一种类型的。比如拿三国杀游戏来说,有主公、武将的概念,而不同的人物又属于某一个势力(魏蜀吴)。此时如果还用工厂模式,需要定义6个工厂类:创建魏国主公工厂类,创建蜀国主公工厂类,创建吴国主公工厂类、创建魏国武将工厂类、创建蜀国武将工厂类、创建吴国武将工厂类。
此时引入抽象工厂模式,在抽象工厂里,并不只是创建一类对象,而是多类对象。此时工厂类便可以缩短为3个:创建魏国主公、武将工厂类,创建蜀国主公、武将工厂类,创建吴国主公、武将工厂类。
二、抽象工厂的实现
1、创建主公、武将接口
public interface IMaster { void ShowKing(); } public interface IGeneral { void ShowKing(); }
2、创建主公、武将类
public class MasterWei : IMaster { public void ShowKing() { Console.WriteLine("The master of {0} is 曹操", this.GetType().Name); } } public class MasterShu : IMaster { public void ShowKing() { Console.WriteLine("The master of {0} is 刘备", this.GetType().Name); } } public class MasterWu : IMaster { public void ShowKing() { Console.WriteLine("The master of {0} is 孙权", this.GetType().Name); } } public class GeneralWei : IGeneral { public void ShowKing() { Console.WriteLine("The general of {0} is 夏侯惇、华雄", this.GetType().Name); } } public class GeneralShu : IGeneral { public void ShowKing() { Console.WriteLine("The general of {0} is 关羽、张飞", this.GetType().Name); } } public class GeneralWu : IGeneral { public void ShowKing() { Console.WriteLine("The general of {0} is 黄盖、高顺", this.GetType().Name); } }
3、创建抽象工厂类、具体工厂类
public abstract class AbstractFactory { public abstract IMaster CreateMaster(); public abstract IGeneral CreateGeneral(); } public class FactoryWei : AbstractFactory { public override IGeneral CreateGeneral() { return new GeneralWei(); } public override IMaster CreateMaster() { return new MasterWei(); } } public class FactoryShu : AbstractFactory { public override IGeneral CreateGeneral() { return new GeneralShu(); } public override IMaster CreateMaster() { return new MasterShu(); } } public class FactoryWu : AbstractFactory { public override IGeneral CreateGeneral() { return new GeneralWu(); } public override IMaster CreateMaster() { return new MasterWu(); } }
4、调用方式
{ AbstractFactory factory = new FactoryWei(); IMaster master = factory.CreateMaster(); IGeneral general = factory.CreateGeneral(); master.ShowKing(); general.ShowKing(); } { AbstractFactory factory = new FactoryShu(); IMaster master = factory.CreateMaster(); IGeneral general = factory.CreateGeneral(); master.ShowKing(); general.ShowKing(); }
三、抽象工厂的缺点
抽象工厂是一种倾斜的可扩展设计。把每一种势力称为一个产品簇,比如魏国是一种产品簇,吴国也是、蜀国也是。而产品簇下面有不同产品,对应主公、武将各是一种产品。
而倾斜的可扩展设计指的是,要扩展一种新产品簇(势力)很方便,但要扩展一种产品(人物类型)需要修改工厂。
比如此时要新增一种势力(产品簇)叫:群雄势力,群雄势力的主公代表是张角,而武将代表是吕布。此时要新增这种势力,只需要新增群雄主公类、群雄武将类、群雄工厂,代码如下:
public class FactoryQun : AbstractFactory { public override IGeneral CreateGeneral() { return new GeneralQun(); } public override IMaster CreateMaster() { return new MasterQun(); } } public class MasterQun : IMaster { public void ShowKing() { Console.WriteLine("The master of {0} is 张角", this.GetType().Name); } } public class GeneralQun : IGeneral { public void ShowKing() { Console.WriteLine("The general of {0} is 吕布", this.GetType().Name); } }
调用方式也很简单
{ AbstractFactory factory = new FactoryQun(); IMaster master = factory.CreateMaster(); IGeneral general = factory.CreateGeneral(); master.ShowKing(); general.ShowKing(); }
但是!如果此时要新增一种人物类型(产品),比如除了主公、武将,还有一种重要类型叫:军师。那此时就必须修改工厂了,因为之前的工厂只能创建主公、武将。此时需要对抽象工厂新增一个抽象方法
public abstract class AbstractFactory { public abstract IMaster CreateMaster(); public abstract IGeneral CreateGeneral(); public abstract IAdvisor CreateAdvisor(); }
而一旦抽象类新增了抽象方法了,子类就必须实现这个方法,这样就会修改比较多代码了。
因此,抽象工厂适合的场景是:产品簇不固定,但是产品簇里的产品比较固定的场景。
比如ADO.NET,产品簇为:sqlserver、mysql、Oracle,如果有需要,可以新增sqlLite或者其他数据库。但是他们所需要的对象(产品)都已经固定了,只需要DBCommand、DBConnection、DBDataAdapter、DBParameter就足够了。