设计模式——工厂模式(简单工厂、工厂方法、抽象工厂)

news/2024/10/21 7:58:23/

是什么?

工厂模式的目的是将创建对象的具体过程隐藏起来,从而达到更高的灵活性

工厂模式分为:简单工厂模式、工厂方法模式、抽象工厂模式

为什么?

在Java中,万物皆是对象,我们在使用的时候这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,那么所有new的地方都需要修改一遍,这明显违背了设计原则中的开闭原则,如果我们使用工厂来生产对象,那么我们只需要和工厂打交道就好了,彻底和对象解耦,如果要更换对象,直接在工厂中更换该对象即可,达到了与该对象解耦的目的,因此工厂模式最大的优点就是:解耦

简单工厂模式

简单工厂不是一个设计模式,它更像是一种编码习惯

结构

抽象产品:定义了产品的规模,描述了产品的主要特性和功能。

具体产品:实现或者继承抽象产品的子类。

具体工厂:提供了创建产品的方法,调用者通过该方法来获取产品。

实现

产品类:

public class Car {  //汽车父类private String getName;}
public class Tesla extends Car{   //子类-特斯拉汽车public Tesla() {System.out.println("()=>制造特斯拉汽车");}
}
public class Benz extends Car{  //子类-奔驰汽车public Benz() {System.out.println("()=>制造奔驰汽车");}
}

工厂类及用户使用:

public class SimpleFactory {/*** 。模拟简单工厂模式* */public Car getCar(String type){    //汽车“生产间”=》简单工厂if ("Benz".equals(type)){return new Benz();}if ("Tesla".equals(type)){return new Tesla();}return new Car();}
}
public class Customer {//消费者直接调用的是工厂而非对象本身,这样就将用户和创建对象的过程隔离开来了public static void main(String[] args) {SimpleFactory simpleFactory = new SimpleFactory();simpleFactory.getCar("Benz");}
}

优缺点

我们会发现,在简单工厂模式中,提供了专门的工厂类来帮助我们创建对象,实现了对象创建和用户使用的职责分离,客户端不需要知道所创建的产品类名以及创建过程只需要知道具体产品类所需要的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性;

但是这样做也是不符合“开闭原则的”,如果我们这个时候需要再添加一个BMW汽车,那么同样的需要去修改我们的工厂类,在产品类型较多的时候,有可能造成工厂逻辑过于复杂,不利于系统的横向扩展和维护,并且工厂类集中了所有产品的创建逻辑,如果不能正常工作那么整个系统都会受到影响

为了解决简单工厂出现的问题,引入了我们的工厂方法模式

工厂方法模式

定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象,工厂方法使一个产品类的实例化延迟到其工厂的子类;

结构

抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品;

具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建;

抽象产品:定义了产品的规范,描述了产品的主要特性和功能;

具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应;

实现

产品类:

public class Car {// 产品父类}public class Benz extends Car{  //子类产品public Benz() {System.out.println("()=>制造奔驰汽车");}
}
public class Tesla extends Car{   //子类产品2public Tesla() {System.out.println("()=>制造特斯拉汽车");}
}

抽象工厂

public interface AbstractFactoryInterface {  //抽象工厂Car createCar();
}

具体工厂及用户使用

public class BenzFactory implements AbstractFactoryInterface{  //具体子类工厂@Overridepublic Car createCar() {return new Benz();}
}public class TeslaFactory implements AbstractFactoryInterface{  //具体子类工厂2@Overridepublic Car createCar() {return new Tesla();}
}
public class Customer {   //用户类public static void main(String[] args) {Car car = new BenzFactory().createCar();Car car2 = new TeslaFactory().createCar();}
}

那么我们这个时候还需要添加一个BMW车的话,只需要创建一个BMW类去继承Car,并且再去创建一个BMW的工厂去实现抽象工厂即可,不需要去修改原来的代码,问题即得到解决;

优缺点

用户只需要知道具体工厂的名称即可得到所要的产品,也不需要知道产品具体的类和创建过程,在系统增加新的产品的时候只需要添加具体产品类和对应具体工厂类,无需对源代码进行任何修改,满足开闭原则;

但是每增加一个产品就需要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度;

抽象工厂模式

我们前面介绍的工厂方法模式中考虑的是一类产品的生产,如车厂只生产车,畜牧场只生产动物;

这些工厂只生产同种类的产品,也就是说工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂都是综合型的工厂,能够生产多等级的产品,例如一个畜牧场它不仅生产动物,还生产饲料粮食,汽车厂不仅生产汽车,还生产发动机、汽车配饰等等;

因此抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族如下:横轴是产品等级,也就是同一类产品,纵轴是产品族,也就是同一品牌的产品(产自同一个工厂);

也就是说它是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构;

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可以生产多个等级的产品;

结构

抽象工厂:提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品;

具体工厂:主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建;

抽象产品:定义了产品的规模,描述的产品的主要特性和功能,抽象工厂模式中有多个抽象产品;

具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它与具体工厂之间是多对一的关系;

实现

也就是说我们现在车厂不仅要生产车,还要生产车的配饰、配件等等;

抽象产品及具体产品

public class Engine {public Engine() {}
}public class V12Engine extends Engine{public V12Engine() {System.out.println("这是V12发动机");}
}public class V8Engine extends Engine{public V8Engine() {System.out.println("这是V8发动机");}
}public class Acc {public Acc() {}
}
public class Cowhide extends Acc{public Cowhide() {System.out.println("这是牛皮坐垫");}
}public class Common extends Acc{public Common() {System.out.println("这是普通坐垫");}
}

抽象工厂

public interface AbstractFactory {//抽象工厂,定义创建具体工厂的规范Acc createAcc();Engine createEngine();
}

具体工厂

public class TeslaFactory implements AbstractFactory{//不同的具体产品根据自己的生产需求去创建不同的对象@Overridepublic Acc createAcc() {return new Cowhide();}@Overridepublic Engine createEngine() {return new V12Engine();}
}public class BMWFactory implements AbstractFactory{@Overridepublic Acc createAcc() {return new Common();}@Overridepublic Engine createEngine() {return new V8Engine();}
}

用户

public class Customer {public static void main(String[] args) {TeslaFactory teslaFactory = new TeslaFactory();teslaFactory.createEngine();teslaFactory.createAcc();System.out.println("————————————————————————");BMWFactory bmwFactory = new BMWFactory();bmwFactory.createAcc();bmwFactory.createEngine();}
}

 优缺点

当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象;

但是当产品组中需要增加一个新的产品时所有的工厂类都需要进行修改;

例如我如果想要再添加一个空调这个产品,不仅需要多一个空调的产品族,并且在抽象工厂中还需要添加一个创建空调的方法;


http://www.ppmy.cn/news/61343.html

相关文章

Flask的CBV写法与源码分析

CBV 写法 from flask import Flask from flask.views import MethodViewapp Flask(__name__)class Index(MethodView):def get(self):return getdef post(self):return postapp.add_url_rule(/index,view_funcIndex.as_view(nameindex))if __name__ __main__:app.run()注意&…

libfacedetection 人脸检测库 检测速度慢的问题

目录 一、libfacedetection 性能介绍 英特尔CPU 使用AVX2指令集 使用AVX512指令集 嵌入式设备 二、加速检测速度 libfacedetetion的前向推理速度很快的原因 使用axv2加速指令 一、libfacedetection 性能介绍 在上一篇文章中,我发现使用摄像头检测,构…

华为EC6108V9E/EC6108V9I_rk3228_安卓4.4.4_通刷_卡刷固件包

华为EC6108V9E/EC6108V9I_rk3228_安卓4.4.4_通刷_卡刷固件包-内有教程 特点: 1、适用于对应型号的电视盒子刷机; 2、开放原厂固件屏蔽的市场安装和u盘安装apk; 3、修改dns,三网通用; 4、大量精简内置的…

Kettle安装与使用

一、Kettle简介 Kettle最早是一个开源的ETL(Extract-Transform-Load的缩写)工具,全称为KDE Extraction, Transportation, Transformation and Loading Environment。后来Kettle重命名为Pentaho Data Integration 。它由Java开发,…

基于改进的离散PSO算法的FJSP的研究(Python代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

学计算机的要不要考研?校招工作不喜欢怎么办?怎样才可以年薪百万?

昨天有粉丝私信我 学的计算机 说他大四马上就要毕业了 然后学校分配的这个工作不是很喜欢 问要不要换个方向 然后身边还有一些同学去考研了 说他要不要考研 等等比较典型的一些问题 所以我总结了一下有三个问题 第一个问题 就学计算机的现在工作不好找 要不要考研 第二个问题就…

BetaFlight统一硬件配置文件研读

BetaFlight统一硬件配置文件研读 1. 源由2. 分析2.1 硬件SOC2.2 统一配置文件2.3 cli命令2.4 板级配置主要命令2.4.1 board_name2.4.2 manufacturer_id2.4.3 resource2.4.4 timer2.4.5 dma2.4.6 serial2.4.7 set2.4.8 feature 3. 实例研读3.1 C遗留配置3.2 BoardName - AOCODAR…

普通2本,去过字节外包,到现在年薪25W+的测试开发,我的2年转行心酸经历...

个人简介 我是一个普通二本大学机械专业毕业,17年毕业,19年转行,目前做IT行业的软件测试已经有3年多,职位是高级测试工程师,坐标上海… 我想现在我也有一点资格谈论关于转行这个话题;希望你在决定转行之前…