前言
工厂模式(Factory Pattern)是Java中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的绝佳方式。
工厂模式概述
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象,通常我们其在父类中提供一个创建对象的方法,然后利用子类决定实例化对象的类型。
在《设计模式》中,工厂模式被分为了三种:简单工厂、工厂方法和抽象工厂。(在书中作者将简单工厂模式看作是工厂方法模式的一种特例,也就是说简单工厂的模式是不属于GOF的23种经典设计模式的)。
简单工厂模式
简单工厂不是一种设计模式,反而比较像是一种编程习惯。简单工厂模式又叫做静态工厂方法模式(static Factory Method pattern),它是通过使用静态方法接收不同的参数来返回不同的实例对象。
- 实现方式: 定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。
- 适用场景:需要创建的对象较少、客户端不关心对象的创建过程。
简单工厂包含如下几个角色:
- 抽象产品:定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品:实现或者继承抽象产品的子类
- 具体工厂:提供了创建产品的方法,调用者通过该方法来获取产品。
CarInfo
/**
* @author Duansg
* @date 2022-12-14 11:46 下午
*/
@Data
@Builder
public class CarInfo {
/**
* 汽车品牌名称
*/
private String carName;
/**
* 用户名称
*/
private String userName;
//....
}
Cars
/**
* @author Duansg
* @date 2022-12-14 11:46 下午
*/
public interface Cars {
/**
* 发送汽车
*
* @param userName 用户名称
* @return
*/
Response<CarInfo> sendCars(String userName);
}
BmwCar
/**
* @author Duansg
* @date 2022-12-14 11:48 下午
*/
public class BmwCar implements Cars {
@Override
public Response<CarInfo> sendCars(String userName) {
return Response.ok(
CarInfo.builder().userName(userName).carName("宝马汽车").build()
);
}
}
BenzCar
/**
* @author Duansg
* @date 2022-12-14 11:52 下午
*/
public class BenzCar implements Cars {
@Override
public Response<CarInfo> sendCars(String userName) {
return Response.ok(
CarInfo.builder().userName(userName).carName("奔驰汽车").build()
);
}
}
AudiCar
/**
* @author Duansg
* @date 2022-12-14 11:52 下午
*/
public class AudiCar implements Cars {
@Override
public Response<CarInfo> sendCars(String userName) {
return Response.ok(
CarInfo.builder().userName(userName).carName("奥迪汽车").build()
);
}
}
CarFactory
/**
* @author Duansg
* @date 2022-12-14 11:54 下午
*/
public class CarFactory {
/**
*
* @param carName
* @param userName
* @return
*/
public static Response<CarInfo> getCar(String carName, String userName) {
Cars cars = null;
if ("宝马汽车".equals(carName)) {
cars = new BmwCar();
} else if ("奔驰汽车".equals(carName)) {
cars = new BenzCar();
} else if ("奥迪汽车".equals(carName)) {
cars = new AudiCar();
}
if (null == cars ) {
return Response.failOfMessage("暂无库存");
}
return cars.sendCars(userName);
}
}
Test Unit
/**
* @author Duansg
* @date 2022-12-14 11:59 下午
*/
public class Test {
public static void main(String[] args) {
final Response<CarInfo> bmw = CarFactory.getCar("宝马汽车", "晓断");
// {"result":{"carName":"宝马汽车","userName":"晓断"},"success":true}
System.out.println(JSON.toJSONString(bmw));
final Response<CarInfo> benz = CarFactory.getCar("奔驰汽车", "晓断");
// {"result":{"carName":"奔驰汽车","userName":"晓断"},"success":true}
System.out.println(JSON.toJSONString(benz));
final Response<CarInfo> audi = CarFactory.getCar("奥迪汽车", "晓断");
// {"result":{"carName":"奥迪汽车","userName":"晓断"},"success":true}
System.out.println(JSON.toJSONString(audi));
}
}
小结
简单工厂模式的缺点显而易见,如果我们新增一个劳斯莱斯的产品的时候,需要修改工厂类的代码,违背了"开闭原则"。其优点在于它封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。