概念
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
简介
作用及优势
-
将一组创建规则类似的产品分为一家工厂创建,易于管理;这类我们称为产品族;
-
可以减少很多if else,相当于简单工厂的再次抽象;
-
增加新的具体工厂和产品族很方便,无须修改之前已有的逻辑
- 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
不足之处
- 产品族扩展非常困难,要增加一个系列的某一产品,不仅要在抽象工厂里面加类型,还要在加具体工厂,然后再加指定产品;所以这种适合非常明确目标的场景下去初始化建设!
场景
-
一个网站适应所有的浏览器
- 一个应用程序,适用于所有的操作系统
代码
案例描述
假设有个电脑工厂(抽象工厂),他可以生产屏幕、也可以生产硬盘,但是电脑工厂就是管理产品族的,实际要去实现生产产品的是屏幕工厂,也就是具体工厂去调用实现真正的生产产品逻辑,硬盘工厂也是如此;(脑子懵懵的没关系,根据代码能更好理解)
其实这种模式在平时开发用的不算多,大多数情况下通过简单工厂就能完成,而且这种模式下,会导致子类工厂需要去实现自己没有的功能,这样不算符合接口隔离原则,但是我们可以稍作修改,看下图,我们可以在新增一个中间实现(CommonFactory),他不做任何处理,就替代功能类去实现自己没能力完成的功能,他自己的作用就是减少冗余的无用的代码;
工程目录
项目类图
具体实现
屏幕接口(Monitor ):用于生产屏幕;
/**
* @author chengxing.wu
* @date 2021/6/15 17:59
*/
public interface Monitor {
/**
* 生产屏幕
*/
void createMonitor();
}
屏幕具体实现:Ips屏幕和曲面屏;
/**
* @author chengxing.wu
* @date 2021/6/15 18:04
*/
public class IpsMonitor implements Monitor {
@Override
public void createMonitor() {
System.out.println("==== 生产ips屏 ====");
}
}
---------------------------------
/**
* @author chengxing.wu
* @date 2021/6/15 18:02
*/
public class QmpMonitor implements Monitor {
@Override
public void createMonitor() {
System.out.println("==== 生产曲面屏 ====");
}
}
硬盘抽象类(HardDisk):用于生产硬盘;
/**
* @author chengxing.wu
* @date 2021/6/15 18:05
*/
public interface HardDisk {
/**
* 生产硬盘
*/
void createHardDisk();
}
硬盘具体实现:有固态硬盘和机械硬盘
/**
* @author chengxing.wu
* @date 2021/6/15 18:07
*/
public class SSDHardDisk implements HardDisk {
@Override
public void createHardDisk() {
System.out.println("==== 生产ssd硬盘 ====");
}
}
---------------------------------
/**
* @author chengxing.wu@xiaobao100.com
* @date 2021/6/15 18:06
*/
public class MechanicalHardDisk implements HardDisk {
@Override
public void createHardDisk() {
System.out.println("==== 生产机械硬盘 ====");
}
}
电脑工厂(抽象工厂ComputerFactory ):
/**
* @author chengxing.wu
* @date 2021/6/15 17:50
*/
public abstract class ComputerFactory {
/**
* 抽象工厂,电脑工厂既可以生产屏幕,又可以生产硬盘,但是这些都交给对应的厂商去做,自己不做(有子类工厂去做)
*
* @param type
* @return
*/
public abstract Monitor getMonitor(String type);
public abstract HardDisk getHardDisk(String type);
}
电脑工厂:这里只负责去获取对应的具体工厂(具有调用具体逻辑实现能力的工厂== 其实就是一个简单工厂);而这个抽象工厂之后会有一个工厂创造器去生产指定类型的工厂;这个之后看测试代码就很清晰!
-
比如:ProduceFactory 工厂创造器里面传入hdf 就会生成一个硬盘工厂(HardDiskFactory)ComputerFactory;
-
Monitor getMonitor(String type);最后这个返回的对象是由具体对象(HardDiskFactory)生成的;
- 关系:ProduceFactory → ComputerFactory(tips);→ SSDHardDisk
tips: ComputerFactory的类型是(HardDiskFactory),其实就是(HardDiskFactory instanceof ComputerFactory )= true
公共继承类(CommonFactory),去除冗余代码;
/**
* 项目: question-study-improve
* <p>
* 功能描述: 公共工厂
*
* @author: WuChengXing
* @create: 2021-07-09 19:01
**/
public class CommonFactory extends ComputerFactory{
@Override
public Monitor getMonitor(String type) {
return null;
}
@Override
public HardDisk getHardDisk(String type) {
return null;
}
}
硬盘生产工厂(HardDiskFactory )
/**
* @author chengxing.wu
* @date 2021/6/15 18:10
*/
public class HardDiskFactory extends CommonFactory {
/**
* 这里不关心屏幕的生产
*
* @param type
* @return
*/
@Override
public HardDisk getHardDisk(String type) {
if ("m".equals(type)) {
System.out.println("xxxxxxxx 准备生产机械硬盘 xxxxxxxx");
return new MechanicalHardDisk();
} else if ("s".equals(type)) {
System.out.println("xxxxxxxx 准备生产机SSD硬盘 xxxxxxxx");
return new SSDHardDisk();
}
return null;
}
}
硬盘生产工厂,这里就是个简单工厂,根据传入的类型,去生产指定的产品;但是这里生产的产品,在抽象工厂里,是一系列类似的东西;而这个工厂也是一个具体工厂;
-
HardDiskFactory 是一个具体工厂,其实就是一个简单工厂的实现
- ComputerFactory.getHardDisk(String type); → HardDiskFactory → SSDHardDisk;这整个链路连在一起就叫产品族;所以说新增一个产品会很麻烦,需要加一条链路;
屏幕生产工厂:跟硬盘的差不多:
/**
* @author chengxing.wu
* @date 2021/6/15 17:58
*/
public class MonitorFactory extends CommonFactory {
@Override
public Monitor getMonitor(String type) {
if ("q".equals(type)) {
System.out.println("xxxxxxxx 准备生产曲面屏 xxxxxxxx");
return new QmpMonitor();
} else if ("i".equals(type)) {
System.out.println("xxxxxxxx 准备生产IPS屏 xxxxxxxx");
return new IpsMonitor();
}
return null;
}
}
工厂创造器:这通过传入指定工厂的类型,去获取对应工厂;
/**
* @author chengxing.wu
* @date 2021/6/15 18:16
*/
public class ProduceFactory {
public static ComputerFactory create(String type) {
if ("mf".equals(type)) {
System.out.println("-------- 联系屏幕工厂 --------");
return new MonitorFactory();
} else if ("hdf".equals(type)) {
System.out.println("-------- 联系硬盘工厂 --------");
return new HardDiskFactory();
}
return null;
}
}
测试
/**
* @author chengxing.wu@xiaobao100.com
* @date 2021/6/15 18:19
*/
public class AbstractFactoryTest {
public static void main(String[] args) {
// 获取到 屏幕的生产工厂
ComputerFactory monitorFactory = ProduceFactory.create("mf");
// 获取到 曲面屏
Monitor qmp = monitorFactory.getMonitor("q");
//开始生产
qmp.createMonitor();
Monitor ips = monitorFactory.getMonitor("i");
ips.createMonitor();
ComputerFactory hardDiskFactory = ProduceFactory.create("hdf");
HardDisk mechanicalHardDisk = hardDiskFactory.getHardDisk("m");
mechanicalHardDisk.createHardDisk();
HardDisk ssdHardDisk = hardDiskFactory.getHardDisk("s");
ssdHardDisk.createHardDisk();
}
}
结果:
-------- 联系屏幕工厂 --------
xxxxxxxx 准备生产曲面屏 xxxxxxxx
==== 生产曲面屏 ====
xxxxxxxx 准备生产IPS屏 xxxxxxxx
==== 生产ips屏 ====
-------- 联系硬盘工厂 --------
xxxxxxxx 准备生产机械硬盘 xxxxxxxx
==== 生产机械硬盘 ====
xxxxxxxx 准备生产机SSD硬盘 xxxxxxxx
==== 生产ssd硬盘 ====
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/210148.html