1:主题拆解
①基本介绍
②三国杀场景分析
③抽象工厂优缺点
④使用场景分析
⑤三大工厂对比总结
2:基本介绍
创建相关或依赖对象的家族,而无需明确指定具体类。
①为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
②抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品
③使用抽象工厂模式一般要满足以下条件:
系统中有多个产品族, 每个具体工厂创建同族但属于不同等级的产品
系统一次只可能消费其中某一族产品,即同族的产品一起使用。
3:三国杀场景分析
咱们基于一款比较热门的手游三国杀来拆解抽象工厂模式
1:基础版
①定义主公与武将接口,都包括一下显示自己名字的show方法
public interface IGroup
{
void ShowGroup();
}
public interface IGenerals
{
void ShowGenerals();
}
②定义主公与武将实现。我们预备三个势力,魏蜀吴
魏
public class GroupWei : IGroup
{
public void ShowGroup()
{
Console.WriteLine($"{this.GetType().Name} is 曹操");
}
}
public class GeneralsWei : IGenerals
{
public void ShowGenerals()
{
Console.WriteLine($"武将:许诸,徐晃,张辽,夏侯渊,典韦");
}
}
蜀
public class GroupShu : IGroup
{
public void ShowGroup()
{
Console.WriteLine($"{this.GetType().Name} is 刘备");
}
}
public class GeneralsShu : IGenerals
{
public void ShowGenerals()
{
Console.WriteLine($"武将:关羽,张飞,赵云,马超,黄忠");
}
}
吴
public class GroupWu : IGroup
{
public void ShowGroup()
{
Console.WriteLine($"{this.GetType().Name} is 孙权");
}
}
public class GeneralsWu : IGenerals
{
public void ShowGenerals()
{
Console.WriteLine($"武将:黄盖,程普,祖茂,甘宁,吕蒙");
}
}
③上端调用游戏开战
IGroup groupWei = new GroupWei();
IGenerals generalsWei = new GeneralsWei();
groupWei.ShowGroup();
generalsWei.ShowGenerals();
IGroup groupShu = new GroupShu();
IGenerals generalsShu = new GeneralsShu();
groupShu.ShowGroup();
generalsShu.ShowGenerals();
IGroup groupWu = new GroupWu();
IGenerals generalsWu = new GeneralsWu();
groupWu.ShowGroup();
generalsWu.ShowGenerals();
分析:从上端的调用可以知道我们照样是在面向细节编程,基于抽象的处理,我进行第二版本的升级
2:升级版
基于简单工厂模式对细节进行抽象
①三方势力简单工厂封装
public class FactoryWei
{
public IGroup CreateGroup()
{
return new GroupWei();
}
public IGenerals CreateGenerals()
{
return new GeneralsWei();
}
}
public class FactoryShu
{
public IGroup CreateGroup()
{
return new GroupShu();
}
public IGenerals CreateGenerals()
{
return new GeneralsShu();
}
}
public class FactoryWu
{
public IGroup CreateGroup()
{
return new GroupWu();
}
public IGenerals CreateGenerals()
{
return new GeneralsWu();
}
}
②上端面向抽象编程,继续开战
FactoryWei factoryWei = new FactoryWei();
IGroup groupWei = factoryWei.CreateGroup();
IGenerals generalsWei = factoryWei.CreateGenerals();
groupWei.ShowGroup();
generalsWei.ShowGenerals();
FactoryShu factoryShu = new FactoryShu();
IGroup groupShu = factoryShu.CreateGroup();
IGenerals generalsShu = factoryShu.CreateGenerals();
groupShu.ShowGroup();
generalsShu.ShowGenerals();
FactoryWu factoryWu = new FactoryWu();
IGroup groupWu = factoryShu.CreateGroup();
IGenerals generalsWu = factoryWu.CreateGenerals();
groupWu.ShowGroup();
generalsWu.ShowGenerals();
分析:我们从业务场景中进行挖掘,可以发现每一方势力,都有ShowGroup和ShowGenerals方法,因此我们基于抽象可以进一步进行升级
3:最终版
对每个工厂的相同点进行抽象
①添加抽象工厂类,包含了ShowGroup和ShowGenerals两个抽象方法
public abstract class AbstractFactory
{
public abstract IGroup CreateGroup();
public abstract IGenerals CreateGenerals();
}
②工厂类进行调整
public class FactoryWei: AbstractFactory
{
public override IGroup CreateGroup()
{
return new GroupWei();
}
public override IGenerals CreateGenerals()
{
return new GeneralsWei();
}
}
public class FactoryShu: AbstractFactory
{
public override IGroup CreateGroup()
{
return new GroupShu();
}
public override IGenerals CreateGenerals()
{
return new GeneralsShu();
}
}
public class FactoryWu: AbstractFactory
{
public override IGroup CreateGroup()
{
return new GroupWu();
}
public override IGenerals CreateGenerals()
{
return new GeneralsWu();
}
}
分析:至此为止,抽象工厂模式已经成型。
4:可扩展
如果游戏在三方势力之外,又添加第四方势力,例如 群雄。此时基于抽象工厂模式是如何实现程序的可扩展性呢?咱们继续拆解
①添加群雄的公主类和武将类,基础自对应的接口,并且实现
public class GroupQun : IGroup
{
public void ShowGroup()
{
Console.WriteLine($"{this.GetType().Name} is 张角");
}
}
public class GeneralsQun : IGenerals
{
public void ShowGenerals()
{
Console.WriteLine($"武将:吕布,颜良,文丑,华雄");
}
}
②添加群雄工厂类,继承抽象工厂并且对其中的方法进行重写
public class FactoryQun: AbstractFactory
{
public override IGroup CreateGroup()
{
return new GroupQun();
}
public override IGenerals CreateGenerals()
{
return new GeneralsQun();
}
}
分析:此时我们在不改任何代码的情况下,为整个产品族添加了新的功能。
5:倾斜的可扩展性
如果新加的势力,比较强势,不仅仅有主动和武将两个技能,还有军师这个角色,或者只有上面两大角色中的一种,此时就需要对抽象工厂类进行更改,这种改过无疑是毁灭性的,也是不符合对修改关闭对扩展开放的原则。
①抽象工厂对产品簇扩展方便,工厂职责不能扩展。
②可以用倾斜的可扩展性设计来描述抽象工厂模式。
③使用抽象工厂,应该确保工厂职责在固定/稳定的情况下。
4:抽象工厂优缺点
1:优点
①对象的创建转移到了工厂,延迟了对象的创建,上端与下端没有依赖。
②在工厂方法的基础上,一个类中的方法拆分成多个方法,各个方法职责单一,简化了代码。也方面了横向扩展。
③当增加一个新的产品族时不需要修改原代码,满足开闭原则。
2:缺点
当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。
5:使用场景分析
1:ADO.NET中SqlClient
从上图中我们可以发现在SqlClient的工厂类就是继承抽象工厂DbProviderFactory,任何只要继承了DbProviderFactory并且对其中的虚方法进行重写,则可以实现对应职责的功能。
2:自己项目中访问数据库方式的扩展
基于这种思想,加入项目中数据访问层,如果以前是用的MSSQL,现在要更改为mysql,抽象工厂可以再扩展一个mysql的数据访问模块。
数据的四种操作方法,增删改查
①定义一个抽象工厂BaseFactory,包括增删改查四种方法(抽象)
②Mysql的工厂继承抽象工厂BaseFactory,并且override其中的四种方法
③SQLSERVER的工厂继承抽象工厂BaseFactory,并且override其中的四种方法
6:三大工厂对比总结
1:简单工厂
是用于解决上端与下端的耦合,解决对象的创建。把对象的创建转移到工厂里面去,将矛盾转移并且集中了.
好处:在上端中屏蔽的类细节,而是把细节延迟到了工厂里面去
缺点:工厂类不稳定,耦合了很多方法,职责太多,违法了单一职责原则。
2:工厂方法
是对简单工厂中工厂类中的创建进行拆分,分离了简单工厂类中的职责,这样工厂类也变的稳定了。
好处:对扩展开发,对修改封闭,完美了支持了开闭原则
缺点:代码变得复杂。每个类的创建都需要创建一个工厂,并且此工厂也只负责一个类的创建
场景应用:HttpHandler,对于aspx,ashx,asmx都有一个独立的工厂方法的使用
3:抽象工厂
用来解决产品级的扩展,产品要做横向扩展时,需要一个东西去约束他,保证他扩展的时候要达到的条件,即抽象工厂的约束,即满足了这个扩展的条件。
4:工厂方法VS简单工厂
工厂方法是将简单工厂,一个类拆成多个类,抽象工厂是将简单工厂,一个类中的方法拆成多个方法。
5:工厂方法VS抽象工厂
工厂方法是扩展某一个种族(纵向扩展)。但是这个种族都是属于一种游戏。而抽象工厂是扩展一款游戏(横向扩展)