设计模式------工厂模式
目录
1、概述
工厂模式分为简单工厂模式,工厂方法模式和抽象工厂模式,它们都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,目的是降低系统中代码耦合度,并且增强了系统的扩展性。本文对这三种模式进行了介绍并且分析它们之间的区别。
2、简单工厂模式
2.1 什么是简单工厂模式
定义一个工厂类,并提供一个抽象工厂方法,该方法通过传入不同的入参而制造出特定的产品,且所有产品具有共同的父类。
2.2 优点与缺点
优点:实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责
缺点:工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码逻辑将会非常复杂。
2.3 结构图
- 简单工厂模式中的类存在以下几种角色:
- Product(抽象产品角色):所有具体产品的父类
- Factory(工厂角色):实现产品创建逻辑的类
- ConcreteProduct(具体产品角色) : 继承自抽象产品类的具体实现类
- 工厂类中包含静态工厂方法,出参为产品类,客户端通过传入不同入参去调用静态工厂方法去获取不同的具体产品类
- 工厂类中的静态工厂方法通过if else 判断去实例化不同的具体产品类
2.4 简单实例
抽象产品
interface Chart {
void display();
}
具体产品类
public class HistogramChart implements Chart {
public HistogramChart() {
System.out.println("创建了柱状图");
}
@Override
public void display() {
System.out.println("显示柱状图");
}
}
public class ZhexianChart implements Chart {
public ZhexianChart () {
System.out.println("创建了折行图");
}
@Override
public void display() {
System.out.println("显示折行图");
}
}
静态工厂
public class ChartFactory {
public static Chart getChart(String type) {
Chart chart = null;
if (type.equalsIgnoreCase("histogram")) {
chart = new HistogramChart();
System.out.println("初始化设置柱状图");
} else if (type.equalsIgnoreCase("折线")) {
chart = new ZhexianChat();
System.out.println("初始化设置折线图");
}
return chart;
}
}
客户端:
public class Client {
public static void main(String[] args) {
Chart chart = ChartFactory.getChart("histogram");
chart.display();
}
}
3、工厂方法模式
3.1 什么是工厂方法模式
此模式中,通过定义一个抽象的核心工厂类,并定义创建产品对象的接口,创建具体产品实例的工作延迟到其工厂子类去完成。通俗点说就是,我有一个大公司,你们需要什么产品就跟我说,我交给我的子公司去生产给你(个人理解)。
3.2 工厂方法模式的优缺点
优点:核心类只关注工厂类的接口定义,而具体的产品实例交给具体的工厂子类去创建。当系统需要新增一个产品是,无需修改现有系统代码,只需要添加一个具体产品类和其对应的工厂子类,使系统的扩展性变得很好,符合面向对象编程的开闭原则。
缺点:在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
3.3 结构图
- 工厂模式中的类共分为以下几种角色:
- Factory(抽象工厂):提供具体工厂所需要实现的接口集合,供客户端调用
- ConcreteFactory(具体工厂):每一个具体的工厂生产一种具体的产品
- Product(抽象产品):所有具体产品的父类
- ConcreteProduct(具体产品):实现抽象产品类的具体的类,与具体工厂一一对应
- 实例化具体工厂并将指针赋予抽象工厂
- 调用抽象工厂的工厂方法,创建具体产品
3.4 简单的实例
抽象产品
public interface Products {
public void show();
}
具体产品1
public class ConcreteProduct1 implements Products {
@Override
public void show() {
System.out.println("------- 生产产品1 ------");
}
}
具体产品2
public class ConcreteProduct2 implements Products{
@Override
public void show() {
System.out.println("-------- 正在生产产品2 ------------");
}
}
抽象工厂(总公司)
public interface AbstractFactory {
public Products newProducts();
}
具体工厂1
public class ConcreteFactory1 implements AbstractFactory {
@Override
public Products newProducts() {
System.out.println("具体工厂1----》生产产品1");
return new ConcreteProduct1();
}
}
具体工厂2
public class ConcreteFactory2 implements AbstractFactory {
@Override
public Products newProducts() {
System.out.println("具体工厂2----》生产产品2");
return new ConcreteProduct2();
}
}
客户端测试
public class Client {
public static void main(String[] args){
AbstractFactory factory = new ConcreteFactory1();
ConcreteProduct1 product = (ConcreteProduct1) factory.newProducts();
product.show();
}
}
工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。
3.5 典型的应用
(1)Java集合接口 Collection 中的工厂方法模式
Collection 接口扮演了抽象工厂角色,工厂方法为 iterator(),Collection 的实现类譬如 ArrayList 扮演了具体工厂角色,而抽象产品为 Iterator 接口,具体产品为 Itr 类
(2)Logback 中的工厂方法模式
抽象工厂角色为 ILoggerFactory 接口,工厂方法为 getLogger,具体工厂角色为 LoggerContext、NOPLoggerFactory、SubstituteLoggerFactory 等,抽象产品角色为 Logger,具体产品角色为 Logger 的实现类。
4、抽象工厂模式
4.1 什么是抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。
此模式是对工厂方法模式的进一步扩展。在工厂方法模式中,一个具体的工厂负责生产一类具体的产品,即一对一的关系,但是,如果需要一个具体的工厂生产多种产品对象,那么就需要用到抽象工厂模式了。
4.2 抽象工厂的优缺点
优点:
- 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
- 增加新的产品族很方便,无须修改已有系统,符合”开闭原则”
缺点:增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了\”开闭原则”。
4.3 结构图
- 抽象工厂模式总共包含如下四种角色:
- AbstractFactory(抽象工厂):包含多个创建同一产品族中产品的抽象工厂方法的抽象类,一个抽象工厂定义了一个输出的产品族
- ConcreteFactory(具体工厂):抽象工厂的实现
- AbstractProduct(抽象产品):所有具体产品的父类,这里指单一产品的父类而不是一个产品族的共同父类
- ConcreteProduct(具体产品):具体的产品
- 实际上抽象工厂模式与工厂方法模式抽象产品与具体产品的角色是一致的,不同的只是工厂定义的不同,工厂方法中的工厂只生产单一产品,而抽象工厂的工厂生产的是一个产品族的产品
4.4 一个简单实例
抽象产品 Article
和 Video
,他们是产品族的抽象类,有一个 Article
就有一个 Video
public abstract class Article {
public abstract void produce();
}
public abstract class Video {
public abstract void produce();
}
具体产品 JavaArticle
、PythonArticle
、PythonVideo
、JavaVideo
public class JavaArticle extends Article {
@Override
public void produce() {
System.out.println("编写Java课程笔记记");
}
}
public class PythonArticle extends Article {
@Override
public void produce() {
System.out.println("编写Python课程笔记");
}
}
public class JavaVideo extends Video {
@Override
public void produce() {
System.out.println("录制Java课程视频");
}
}
public class PythonVideo extends Video {
@Override
public void produce() {
System.out.println("录制Python课程视频");
}
}
抽象工厂 CourseFactory
,与工厂方法模式不同,工厂方法模式中一个工厂只生产一个产品,而抽象工厂模式中一个工厂生产一族产品,有多个工厂方法
public interface CourseFactory {
Video getVideo();
Article getArticle();
}
具体工厂 JavaCourseFactory
和 PythonCourseFactory
,它们都继承抽象工厂接口 CourseFactory
public class JavaCourseFactory implements CourseFactory {
@Override
public Video getVideo() {
return new JavaVideo();
}
@Override
public Article getArticle() {
return new JavaArticle();
}
}
public class PythonCourseFactory implements CourseFactory {
@Override
public Video getVideo() {
return new PythonVideo();
}
@Override
public Article getArticle() {
return new PythonArticle();
}
}
客户端只需要指定具体工厂,就可以获取该工厂生产的一族产品
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课程笔记
4.5 典型的应用
(1)java.sql 包下的 Connection 接口,该接口定义了与特定数据库的连接 Connection,执行 SQL statements 并返回 results
这里边的抽象工厂模式,Connection 为抽象工厂,工厂方法很多,其中一个抽象产品为 Statement,同时 Statement 也是一个抽象工厂,工厂方法也很多,其中一个抽象产品为 ResultSet,具体工厂和具体产品则为他们的实现类
5、工厂方法模式和抽象工厂模式对比
工厂方法模式和抽象工厂模式的核心区别
- 工厂方法模式利用继承,抽象工厂模式利用组合
- 工厂方法模式产生一个对象,抽象工厂模式产生一族对象
- 工厂方法模式利用子类创造对象,抽象工厂模式利用接口的实现创造对象
参考: