简介
抽象工厂也是比较常用的设计模式,提供一个创建一系列相关或相互依赖对象的接口,无需指定它们具体的类型,是属于创建型设计模式。封装了相同主题的工厂,在使用的时候使用抽象工厂提供的方法来创建对象,不需要关心是怎么获取对象的,将实现细节隐藏起来,使客户端使用变的简单。
适用场景
1、客户端不依赖于产品类实例如何被创建、实现等细节
2、强调一系列相关的产品对象一起使用创建对象需要大量重复的代码
3、提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现;
优点
1、具体产品在应用层代码隔离,无须关心创建细节
2、将一个系列的产品族统一到一起创建
缺点
1、规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
2、增加了系统的抽象性和理解难度
产品族与产品等级结构
如上图很好的描述了什么是产品族、什么是产品等级结构?
抽象工厂是对产品族进行封装,在小米工厂里面生产的空调那肯定是小米空调,生产的冰箱也肯定是小米的冰箱,所以如下图:
而之前的工厂方法是对产品等级结构进行的封装。这个就是工厂方法和抽象工厂的区别。
示例代码
先来看下抽象工厂的类图:
跟工厂方法不同的是他是对产品族创建了工厂,该示例有华为和苹果两个工厂,他们分别可以生产手机和pad,像HuaweiFactory里面创建出来的都是华为的产品,接下来看看具体的类:
FoxconnFactory接口,定义了创建手机和pad的方法,是抽象工厂。
public interface FoxconnFactory {
Mobile produceMobile();
Pad producePad();
}
HuaweiFactory是FoxconnFactory的实现类
public class HuaweiFactory implements FoxconnFactory{
public Mobile produceMobile() {
return new HuaweiMobile();
}
public Pad producePad() {
return new HuaweiPad();
}
}
AppleFactory是FoxconnFactory的实现类
public class AppleFactory implements FoxconnFactory{
public Mobile produceMobile() {
return new AppleMobile();
}
public Pad producePad() {
return new ApplePad();
}
}
Mobile是手机的抽象类
public abstract class Mobile {
public abstract void produce();
}
HuaweiMobile是Mobile的实现类
public class HuaweiMobile extends Mobile {
@Override
public void produce() {
System.out.println("生产华为手机");
}
}
AppleMobile是Mobile的实现类
public class AppleMobile extends Mobile{
@Override
public void produce() {
System.out.println("生产苹果手机");
}
}
Pad是pad的抽象类
public abstract class Pad {
public abstract void produce();
}
HuaweiPad是Pad的实现类
public class HuaweiPad extends Pad {
@Override
public void produce() {
System.out.println("生产华为pad");
}
}
ApplePad是Pad的实现类
public class ApplePad extends Pad {
@Override
public void produce() {
System.out.println("生产苹果pad");
}
}
AbstractFactoryTest为测试类
public class AbstractFactoryTest {
public static void main(String[] args) {
FoxconnFactory appleFactory = new AppleFactory();
Mobile appleMobile = appleFactory.produceMobile();
appleMobile.produce();
Pad applePad = appleFactory.producePad();
applePad.produce();
FoxconnFactory huaweiFactory = new HuaweiFactory();
Mobile huaweiMobile = huaweiFactory.produceMobile();
huaweiMobile.produce();
Pad huaweiPad = huaweiFactory.producePad();
huaweiPad.produce();
}
}
如果新增一个产品族,如小米,那么新增一个小米的实现工厂,小米的手机实现类和pad实现类,这样对扩展是开放的,不用修改原先的代码。此时如果新增一个产品等级结构,如需要生产手表,那么需要在FoxconnFactory里面新增一个创建手表的方法,那么相应的工厂实现类都需要修改,这样就违背了开闭原则,所有在选择抽象工厂的时候,需要考虑你的产品等级结构是不是会经常调整?当然如果只是半年或者一年调整一次,那也是可以考虑使用抽象工厂的。
上面示例源码
源码分析
sql中应用
Connection是抽象工厂,ConnectionImpl创建出来的Statement和DatabaseMetaData是mysql的,OracleConnectionWrapper创建出来的Statement和DatabaseMetaData是oracle的。
mybatis中应用
如上类图,可以看出SqlSessionFactory是工厂接口,里面可以创建不同数据库的SqlSession和Configuration,DefaultSqlSessionFactory和SqlSessionManager是工厂的实现,SqlSession和Configuration是相应的产品接口,DefaultSqlSession和SqlSessionManager是产品的实现,不同的数据库可以创建不同类型的工厂。
注意:本文归作者所有,未经作者允许,不得转载