抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
理解产品族和产品等级
产品族:一个品牌下面的所有产品;例如华为下面的手机,路由器,电脑 称为华为的产品族;
产品等级:多个品牌下面的同种产品;例如华为和小米下面的手 称为一个产品等级;
类图分析:
以下图为例,有手机和路由器两种产品,有华为和小米两种品牌,两种品牌都可以生产手机和路由器;
- 有手机和路由器两种产品,定义两个接口;
- 小米和华为都可以生产这两种产品,所以有4个实现类;
- 现在需要创建华为和小米的工厂类,先将工厂类进行抽象,里面有创建两个产品的方法,返回的是产品的接口类;
- 创建华为和小米的工厂实现类,继承工厂类接口,实现创建各自产品的方法;
- 客户端调用时,直接用工厂接口类创建需要的工厂,拿到对应的产品;
代码实现
- 手机产品接口和路由器产品接口
//手机产品接口publicinterfaceIPhoneProduct{//开机voidstart();//关机voidshutdown();//打电话voidcallup();//发邮件voidsendSMS();}//路由器产品接口publicinterfaceIRouterProduct{//开机voidstart();//关机voidshutdown();//打开wifivoidopenwifi();//设置voidsetting();}
- 华为和小米的产品的4个实现类
//华为手机实现类publicclassHuaweiPhoneimplementsIPhoneProduct{@Overridepublicvoidstart(){
System.out.println("开启华为手机");}@Overridepublicvoidshutdown(){
System.out.println("关闭华为手机");}@Overridepublicvoidcallup(){
System.out.println("华为手机打电话");}@OverridepublicvoidsendSMS(){
System.out.println("华为手机发邮件");}}//华为路由器实现类publicclassHuaweiRouterimplementsIRouterProduct{@Overridepublicvoidstart(){
System.out.println("开启华为路由器");}@Overridepublicvoidshutdown(){
System.out.println("关闭华为路由器");}@Overridepublicvoidopenwifi(){
System.out.println("打开华为wifi");}@Overridepublicvoidsetting(){
System.out.println("设置华为路由器");}}//小米手机实现类publicclassXiaomiPhoneimplementsIPhoneProduct{@Overridepublicvoidstart(){
System.out.println("开启小米手机");}@Overridepublicvoidshutdown(){
System.out.println("关闭小米手机");}@Overridepublicvoidcallup(){
System.out.println("小米手机打电话");}@OverridepublicvoidsendSMS(){
System.out.println("小米手机发邮件");}}//小米路由器实现类publicclassXiaomiRouterimplementsIRouterProduct{@Overridepublicvoidstart(){
System.out.println("开启小米路由器");}@Overridepublicvoidshutdown(){
System.out.println("关闭小米路由器");}@Overridepublicvoidopenwifi(){
System.out.println("打开小米wifi");}@Overridepublicvoidsetting(){
System.out.println("设置小米路由器");}}
- 工厂接口类;
//产品工厂接口publicinterfaceIProductFactory{//生产手机
IPhoneProduct phoneProduct();//生成路由器
IRouterProduct routerProduct();}
- 华为和小米工厂实现类,继承工厂接口
//华为工厂实现类publicclassHuaweiFactoryimplementsIProductFactory{@Overridepublic IPhoneProduct phoneProduct(){returnnewHuaweiPhone();}@Overridepublic IRouterProduct routerProduct(){returnnewHuaweiRouter();}}//小米工厂实现类publicclassXiaomiFactoryimplementsIProductFactory{@Overridepublic IPhoneProduct phoneProduct(){returnnewXiaomiPhone();}@Overridepublic IRouterProduct routerProduct(){returnnewXiaomiRouter();}}
- 客户端,通过
IProductFactory
创建各自的工厂,通过工厂拿到对应的产品
publicclassClient{publicstaticvoidmain(String[] args){
System.out.println("============小米产品============");//创建小米工厂
IProductFactory xiaomiFactory =newXiaomiFactory();//生产小米手机
IPhoneProduct xiaomiPhone = xiaomiFactory.phoneProduct();
xiaomiPhone.start();
xiaomiPhone.sendSMS();//生产小米路由器
IRouterProduct xiaomiRouter = xiaomiFactory.routerProduct();
xiaomiRouter.openwifi();
xiaomiRouter.setting();
System.out.println("============华为产品============");//创建华为工厂
IProductFactory huaweiFactory =newHuaweiFactory();//生产华为手机
IPhoneProduct huaweiPhone = huaweiFactory.phoneProduct();
huaweiPhone.start();
huaweiPhone.sendSMS();//生产华为路由器
IRouterProduct huaweiRouter = huaweiFactory.routerProduct();
huaweiRouter.openwifi();
huaweiRouter.setting();}}
抽象工厂模式的实现就是这样,还记得前面讲的产品族和产品等级的概念吗,如果新增一个产品族或产品等级会怎样?
拓展一个产品族
我们会发现,拓展一个产品族是非常困难的,例如产品族中新增一个笔记本电脑,也就是说华为和小米现在可以生产电脑了,如下图所示(黄色字体为新增一个产品族需要做的事),对顶层的工厂接口类也要修改,这是非常麻烦的;
拓展一个产品等级
如果扩展一个产品等级,例如新增一个手机,也就是说新增一个品牌来生产手机,如下图所示(黄色字体为新增一个产品等级需要做的事),新增一个产品等级不用修改原来的代码,符合OCP原则,这是非常舒服的;
所以抽象工厂模式的优缺点
优点:一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象(将一个系列的产品统一一起创建);
缺点:
- 产品族扩展非常困难,要增加一个系列的某一产品,既要修改工厂抽象类里加代码,又修改具体的实现类里面加代码;
- 增加了系统的抽象性和理解难度;
适用场景
- 一系列相关产品对象(属于同一产品族)一起创建时需要大量的重复代码;
- 提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现;
抽象工厂模式符合依赖抽象原则
- 创建对象实例时,不要直接 new一个对象, 而是把创建对象的动作放在一个工厂的方法中;
- 不要让类继承具体类,而是继承抽象类或者是实现接口;
- 不要覆盖基类中已经实现的方法;
版权归原作者 Bee.F 所有, 如有侵权,请联系我们删除。