设计模式—抽象工厂模式(Abstract Factory Pattern)

动机

在了解动机之前,先回顾一下工厂方法模式:

在工厂方法模式中,工厂类都是对单一产品对象进行操作,每一个具体工厂对应一种具体产品,工厂方法具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。

问题:如果想要一个工厂对多个产品对象进行操作,而不是只对单一产品进行操作,那么工厂方法模式就会变得很复杂,如何解决呢?

  • 当系统所提供的工厂所需生产的具体产品并不是一个单一产品,而是多个位于不同继承结构之间的不同类型的产品组成的产品族,这时候就需要使用到抽象工厂模式。

    • 继承结构:如一个抽象类是动物,动物中有狗、猫等等,则动物与狗、猫构成了一种继承结构,动物类是父类,狗、猫是子类。
    • 产品族:指由同一个工厂生产,位于不同继承结构中的一组产品,如动物类中有狗的名称、叫声、吃东西,狗的名称属于名称一类,狗的叫声属于叫声一类,狗吃东西属于吃东西一类。
      在这里插入图片描述
    • 上图中,有名称、叫声、吃东西三个属性,它们之间都没有联系,是单独的,我们将名称、叫声、吃东西三个属性组成一个产品族,用于区分其他动物的名称、叫声、吃东西。每个产品族又可以划分为狗、猫、猪等不同的动物。
  • 抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品的继承结构,而抽象工厂模式则需要面对多个产品的继承结构,一个工厂继承结构可以负责多个不同产品继承结构中的产品对象的创建 。当一个工厂继承结构可以创建出分属于不同产品继承结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。

概述

抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。

角色

抽象工厂模式包含如下角色:

  • AbstractFactory:抽象工厂
  • ConcreteFactory:具体工厂
  • AbstractProduct:抽象产品
  • Product:具体产品
  • UML类图:

案例

  • 实质:抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式能够对多个不同继承结构的不同产品族进行操作。
  • 实现:对产品族的AnimalName/AnimalEat/AnimalShout类进行抽象,分别使用不同的继承对象(DogName/DogShout/DogEat/CatName/CateShout/CatEat)继承产品族的类,然后创建整个动物类的工厂接口(AnimalFactory),最后使用具体的工厂实现类(DogFactory/CatFactory)来实现动物类的工厂接口,并创建该继承对象对应产品族的实例。
  • UML类图:
  • 案例代码:
    • 抽象产品角色(AnimalName/AnimalShout/AnimalEat)
      //AbstractProduct
      abstract class AnimalName{
      	public abstract void name();
      }
      
      abstract class AnimalShout{
      	public abstract void shout();
      }
      
      abstract class AnimalEat{
      	public abstract void eat();
      }
      
    • 具体产品角色(DogName/DogShout/DogEat/CatName/CatShout/CatEat)
      //Product
      class DogName extends AnimalName{
      	@Override
      	public void name() {
      		System.out.println("dog name");
      	}
      }
      
      class CatName extends AnimalName{
      	@Override
      	public void name() {
      		System.out.println("cat name");
      	}
      }
      
      //Product
      class DogShout extends AnimalShout{
      	@Override
      	public void shout() {
      		System.out.println("dog shout");
      	}
      }
      
      class CatShout extends AnimalShout{
      	@Override
      	public void shout() {
      		System.out.println("cat shout");
      	}
      }
      
      //Product
      class DogEat extends AnimalEat{
      	@Override
      	public void eat() {
      		System.out.println("dog eat");
      	}
      }
      
      class CatEat extends AnimalEat{
      	@Override
      	public void eat() {
      		System.out.println("cat eat");
      	}
      }
      
    • 抽象工厂角色(AnimalFactory)
      //AbstractFactory
      interface AnimalFactory{
      	AnimalName animalName();
      	AnimalShout animalShout();
      	AnimalEat animalEat();
      }
      
    • 具体工厂角色(DogFactory/CatFactory)
      //Concrete Factory
      class DogFactory implements AnimalFactory{
      
      	@Override
      	public AnimalName animalName() {
      		return new DogName();
      	}
          
      	@Override
      	public AnimalShout animalShout() {
      		return new DogShout();
      	}
          
      	@Override
      	public AnimalEat animalEat() {
      		return new DogEat();
      	}
      }
      
      class CatFactory implements AnimalFactory{
      
      	@Override
      	public AnimalName animalName() {
      		return new CatName();
      	}
      
      	@Override
      	public AnimalShout animalShout() {
      		return new CatShout();
      	}
      
      	@Override
      	public AnimalEat animalEat() {
      		return new CatEat();
      	}
      }
      
    • 测试类:
      /**
       * 抽象方法模式-动物
       * @author kime
       *
       */
      public class AbstractFactoryAnimal {
      
      	public static void main(String[] args) {
      		AnimalFactory dogFactory = new DogFactory();
      		AnimalFactory catFactory = new CatFactory();
      		common(dogFactory);
      		common(catFactory);
      	}
      	
      	private static void common(AnimalFactory animalFactory) {
      		animalFactory.animalName().name();
      		animalFactory.animalShout().shout();
      		animalFactory.animalEat().eat();
      	}
      }
      
    • 结果:

优点

  • 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。
  • 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。
  • 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。

缺点

  • 在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。
  • 开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)。

场景

在以下情况下可以使用抽象工厂模式:

  • 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
  • 系统中有多于一个的产品族,而每次只使用其中某一产品族。
  • 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
  • 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值