什么是工厂设计模式
工厂是指创建对象的工厂,不同于简单直接new创建一个对象,在一个对象的创建过程变得复杂时,工厂来创建对象优势就明显了。特别是标准化的产品,抽象到接口后,可能有几十个实现类的场景。
举两个例子:
- 一个手机产品接口,定义了手机标准,有打电话功能、联网功能等,具体的实现有小米手机、华为手机等,要根据不同的场景使用不同的实例类
- 一个电脑对象,由CPU、主板、显示屏、电源等组成,不同的厂家不同的实现方式。对于使用者来说,只要拿到电脑对象即可,而不需要关心电脑对象的创建过程
- 可以使用工厂获取到一个产品系列。比如通过小米工厂,可以得到小米手机、小米汽车等;通过华为工厂,可以得到华为手机、华为汽车等
而工厂的实现方式,也有3种
- 简单工厂模式
- 工厂方法模式
- 抽象工厂方法模式
还有一种建造者模式,也是创建对象的方法
简单工厂模式
简单工厂模式其实用的蛮多的,代码逻辑清晰易懂。代码的结构如下:
- 抽象产品接口(定义产品标准的接口,比如定义个手机产品)
- 产品实现类(真正的产品实现,有很多种类型,比如小米手机、华为手机)
- 工厂类(获取产品实现类)
假设有手机这个抽象的产品接口,有2个实现类,分别是小米手机和华为手机,
如图:
小米手机实现类
华为手机实现类
定义简单工厂,通过参数来判断实例化的对象
调用方式
如果后续需要加新的类型,修改简单工厂类SimpleFactory就好,继续在后面加if else。但是这会让代码结构看起来很复杂,而且也违反了开闭原则。
工厂方法模式
为什么解决当要实例化的产品过多时,简单工厂所带来的问题。工厂方法模式诞生了。简单说就是给工厂这个类,加一个抽象类。那么就变成了如下构造:
- 抽象工厂接口
- 抽象工厂实现类(每个产品实现一个工厂)
- 抽象产品接口(定义产品标准的接口)
- 产品实现类(真正的产品)
类的UML图如下:
代码定义如下:
调用时保证了可扩展性
但是这同样会带来一个问题,类的数量会增加,带来复杂性
抽象工厂方法模式
其实与工厂方法模式没什么不同,只是在抽象工厂接口类中,定义一系列的获取工厂方法。如不只要提供获取手机的方法,还要提供获取汽车的方法:
工厂方法模型的抽象工厂接口,只定义获取一个工厂的接口
/**
* 抽象工厂接口
*/
public interface IMethodFactory {
// 工厂需要提供手机产品
IMobilePhone getMobilePhone();
}
抽象工厂方法模式下,工厂接口,提供多个方法。实现者提供该系列的产品
/**
* 抽象工厂方法模式
* 工厂接口,定义多个方法,
* 实现这个接口,即可获取同一个系列的产品
* 即如果调用小米工厂,可以得到小米的手机汽车
* 如果调用华为工厂,可以得到华为的手机和汽车
*/
public interface IAbstractMethodFactory {
// 获取手机
IMobilePhone getMobilePhone();
// 获取汽车
ICar getCar();
}
小米工厂实现
public class MiAbFactory implements IAbstractMethodFactory{
@Override
public IMobilePhone getMobilePhone() {
// 提供小米手机实现
return new MiPhone();
}
@Override
public ICar getCar() {
// 提供小米汽车实现
return new MiCar();
}
}
华为工厂实现
public class HuaweiAbFactory implements IAbstractMethodFactory{
@Override
public IMobilePhone getMobilePhone() {
// 提供华为手机实现
return new HuweiPhone();
}
@Override
public ICar getCar() {
// 提供华为汽车实现
return new HuaweiCar();
}
}
建造者模式
当一个产品,他的创建流程被高度抽象时,可以使用建造者模式。实现类与定义与创建的分裂。
在工业界有一句很好的话概况:“制造工序标准化,制造工艺多样化”。
即产品的创建流程,是被高度标准化的,比如一台电脑,是先创建主板、然后焊接CPU,然后…。这个流程是被高度标准化的(现实可能不同,只是举个例子)。
而产品创建的工艺,是可以多样化的,比如戴尔公司生成CPU这一步,可能温度有更好的要求,华硕公司生成CPU这一步,对时间的要求更好(只是举个例子)。
具体在代码实现里,可以定义这4个类:
- 产品类(定义一个产品有哪些成员变量)
- 抽象Builder类(定义创建产品,需要提供实现哪些方法,提供哪些变量)
- builder实现类(不同的厂家,对产品有不同的实现,但是最终得到的产品是一个标准的)
- Director指挥类(传入builder实现类,然后定义产品类的实现过程,如先组装主板,然后生产CPU等)
下面看一个案例,有一个汽车这个产品,有类型、续航、价格这类成员变量
/**
* 产品 product
* 只定义产品的功能,不负责实现
*/
public class Car {
// 类型 轿车或者suv
String type;
// 续航
int endurance;
// 价格
int price;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getEndurance() {
return endurance;
}
public void setEndurance(int endurance) {
this.endurance = endurance;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
定义抽象构造类,要生成汽车,必须构造他的类型、续航、价格,甚至提供资质
/**
* 抽象构造者
*/
public abstract class CarBuilder {
// 要构造的对象,不提供具体的实现
Car car = new Car();
// 要构造汽车,必须提供汽车类型、续航、价格
protected abstract void builderType();
protected abstract void builderEndurance();
protected abstract void builderPrice();
// 同时,构造汽车,必须提供造车资质
protected abstract String getQualification();
// 构造车的方法
protected abstract Car createCar();
}
然后是不同的厂商对汽车这个标准产品的不同实现
特斯拉厂商
/**
* 特斯拉构造实现类
*/
public class TeslaBuilder extends CarBuilder{
@Override
protected void builderType() {
this.car.setType("model3");
}
@Override
protected void builderEndurance() {
this.car.setEndurance(500);
}
@Override
protected void builderPrice() {
this.car.setPrice(24599);
}
@Override
protected String getQualification() {
return "许可证至....";
}
@Override
protected Car createCar() {
return this.car;
}
}
奔驰厂商
/**
* 奔驰车构造器
*/
public class BenzBuilder extends CarBuilder{
@Override
protected void builderType() {
this.car.setType("eqe");
}
@Override
protected void builderEndurance() {
this.car.setEndurance(300);
}
@Override
protected void builderPrice() {
this.car.setPrice(34500);
}
@Override
protected String getQualification() {
return "许可证.....";
}
@Override
protected Car createCar() {
return this.car;
}
}
最后是指挥类,来统一汽车标准产品的制造流程
/**
* 指挥者
* 定义类创建的流程标准
*/
public class CarDirector {
// 要有一个builder
private CarBuilder builder;
public CarDirector(CarBuilder builder) {
this.builder = builder;
}
/**
* 开启构造
* 这里定义汽车创建的标准流程
*/
public Car construct() {
// 验证资质
if (builder.getQualification() == null) {
// 没有资质....
}
// 先制造轮胎、车身等等
// 先构造类型
builder.builderType();
// 再构造续航
builder.builderEndurance();
// 再构造价格
builder.builderPrice();
// 创建车
return builder.createCar();
}
}
建造者模式就完成了
优点:类之间的职责分明,产品标准化程度高,创建流程也统一便于维护
缺点:产品必须是统一的,产品的创建流程也必须是统一的