抽象工厂
- 定义:抽象工厂模式提供一个创建一系列相关或相互依赖对象接口
- 无须指定他们具体的类
- 类型:创建型
- 抽象工厂可以将一组具有同一主题单独的工作封装起来。
正常使用中,客户端程序,需要创建抽象工厂的具体实现,然后使用抽象工厂,返回接口,来创建这一主题的具体对象。我们使用的时候,是不需要知道和关心,它从这些内部的工厂方法中,获得对象的具体类型。
因为我们的客户端程序仅使用这些对象的通用接口。
抽象工厂模式将一组对象的实现细节和他们的使用分离开来。
使用场景:
- 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
- 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复代码。
- 提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
优点:
- 具体产品在应用层代码隔离,无须关心创建细节
- 将一个系列的产品组统一到一起创建
缺点:
- 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
- 增加了系统的抽象性和理解难度
抽象工厂——产品等级结构与产品族
- 相同颜色的就是代表一个产品族
- 相同椭圆形的颜色深浅不同代表一个产品等级结构
比如
- 横着来看,华为工厂生产【长方形】为华为电脑,【圆形】为华为手表,【椭圆形】为华为手机,他们都是华为的品牌,都属于华为的产品族
- 竖着来看,【椭圆形】都是手机,第一排是华为手机,第二排是小米手机,第三批为苹果手机等等,它们属于同一个产品结构
抽象工厂和工作方法最大区别
- 工厂方法针对是产品等级结构
- 抽象方法针对是产品族
我们只要在华为工厂里面取手机,取出来的肯定是华为手机,所有只要指出一个产品所处的产品族,以及他所处的等级结构,就可以唯一确定这个产品
接着来看,左侧小房子为具体工厂
华为生产出来的,手机、手环,电脑,路由器,全是华为品牌,只要从左侧具体工厂取出来的都是属于同一个产品族
抽象工厂和工厂方法怎么选择,看业务场景
从一个工厂可以创建出一个可分属于不同产品等级结构的一个产品族所有对象时,这个时候抽象工厂模式比工厂方法模式,更为简单。
业务场景
在CSDN中学习课程,课程中包含视频和笔记,java视频,python视频,大数据视频它们处于同一产品等级,都是视频java笔记,python笔记,大数据笔记它们处于同一产品等级,都是笔记java视频,java笔记,它们处于同一产品族,都是java相关的
代码:
先创建课程工厂,使用接口来声明
public interface CourseFactory {
/**视频*/
Video getVideo();
/**笔记*/
Article getArticle();
}
创建抽象类 ,video和article
public abstract class Article {
public abstract void produce();
}
public abstract class Video {
public abstract void produce();
}
下面比较重要环节,课程是视频+笔记,才可以称为课程,那么我们就声明一个产品族工厂
声明java课程的工厂,实现CourseFactory
对比工厂方法,我们使用抽象工厂的时候,来做java课程的时候,并没有声明视频的工厂和手记的工厂,而是声明一个组合到一起的课程工厂,但是具体的产品是有的,具体的java视频,java笔记
java课程包含产品族,它包含视频,包含笔记。
public class JavaCourseFactory implements CourseFactory {
/**视频*/
@Override
public Video getVideo() {
return new JavaVideo();
}
@Override
public Article getArticle() {
return new JavaArticle();
}
}
创建创建java视频javaVideo
public class JavaVideo extends Video {
//java学习视频的实现
@Override
public void produce() {
System.out.println("学习Java课程视频");
}
}
创建java笔记 JavaArticle
public class JavaArticle extends Article {
//java学习手记的实现
@Override
public void produce() {
System.out.println("编写Java课程手记");
}
}
下面再写一套python的课程
创建python的课程工厂PythonCourseFactory ,实现课程工厂CourseFactory
public class PythonCourseFactory implements CourseFactory {
@Override
public Video getVideo() {
return new PythonVideo();
}
@Override
public Article getArticle() {
return new PythonArticle();
}
}
public class PythonVideo extends Video {
@Override
public void produce() {
System.out.println("学习Python课程视频");
}
}
public class PythonArticle extends Article {
@Override
public void produce() {
System.out.println("编写Python课程笔记");
}
}
测试
public class Test {
public static void main(String[] args) {
CourseFactory courseFactory = new JavaCourseFactory();
Video video = courseFactory.getVideo();
Article article = courseFactory.getArticle();
video.produce();
article.produce();
}
}
我想要学习java课程
输出结果
学习Java课程视频
编写Java课程笔记
UML类图分析
产品族的工厂CourseFactory有两个具体的PythonCourseFactory和JavaCourseFactory工厂java课程工厂生产javavideo和java笔记python课程工厂生产pythonvideo和python笔记
而video和article作为整个产品族工作的返回值就是,CourseFactory、PythonCourseFactory、JavaCourseFactory依赖抽象产品video,依赖抽象产品article
要是我这里添加了大数据课程工厂,对于现在的抽象模式工厂很好扩展,对原来的类不需要变化
只需要创建一个大数据课程工厂,创建大数据video,大数据article
还有一个好处,就是test这个客户端,不需要关心这个产品族创建的过程,应用层代码只需要关心他是哪个工厂即可,因为应用层代码不会直接创建java笔记,python手记,与java视频,pyhon视频,因为整个创建过程是交由具体的创建工厂创建的,并且创建是一个产品族产品,这里创建的肯定是java不会错。
源码分析——Connection类
ctrl+N 搜索Connection
数据库连接的接口
返回Statement
返回PreparedStatement
很容易理解,在Connection接口里面中返回都是同一个产品族
例如创建一个mysql的Connection,从这里获取的无论是Statement还是PreparedStatement,都是对于db的连接
也就是mysql取获取的时候,肯定获取到mysql数据连接的Statement
所以这里定义各种不同的方法都是属于同一个产品族
PreparedStatement prepareStatement(String sql)
throws SQLException;
再看下Statement,这也是一个接口
下面有各种返回,都属于同一个Statement,很明显这也是一个抽象工厂
所以在mysql里面很容易就很理解什么是抽象工厂,以及在jdk怎么使用。