工厂工厂,顾名思义就是加工东西的。Java的工厂模式包含以下3种:
-
简单工厂模式
-
工厂方法模式
-
抽象工厂模式
1.简单工厂
使用场景:如果一个一些对象产品,已经确定不会再改动,就可以使用简单工厂模式
理解几个关键点
1)抽象产品角色:它一般是具体产品继承的父类或要实现的接口。
2)具体产品角色:工厂类创建的对象就是该角色的实例。
3)工厂类角色:含有一定的业务逻辑和判断逻辑。
代码实例:
/**
* 抽象产品定义
* */
public interface Car {
/**
* 只要能跑就行
* */
void run();
}
/**
* 具体产品(奔驰)定义:实现抽象产品
* */
public class BenzCar implements Car{
@Override
public void run() {
System.out.println("我是高级轿车Benz,我会跑");
}
}
/**
* 具体产品(宝马)定义:实现抽象产品
* */
public class BMWCar implements Car{
@Override
public void run() {
System.out.println("我是高级轿车BMW,我会跑");
}
}
/**
* 定义一个生产车的工厂
* */
public class CarFactory {
public Car createCar(String carType) {
Car car = null;
switch (carType) {
case "1":
car = new BMWCar();//宝马车
break;
case "2":
car = new BenzCar();//奔驰车
break;
}
return car;
}
}
public class Client {
public static void main(String[] args) {
//生成一个工厂类
CarFactory carFactory = new CarFactory();
/**
* 客户:我要一辆宝马车
* 工厂:好的,马上给你
**/
Car bmwCar = carFactory.createCar("1");
bmwCar.run();
/**
* 客户:我还想在要一辆奔驰车
* 工厂:好的,马上给你
**/
Car benzCar = carFactory.createCar("2");
benzCar.run();
}
}
输出结果:
我是高级轿车BMW,我会跑
我是高级轿车Benz,我会跑
在将工厂方法和抽象工厂模式前,先介绍两个概念,若你把这两个概念搞懂了,理解工厂方法和抽象工厂模式就容易多了。
1)产品等级结构:产品等级结构即产品的继承结构。如一个抽象类是车,其子类有奔驰车,宝马车,大众车等,则抽象车与具体品牌的车之间构成了一个产品等级结构,抽象车是父类,而具体品牌的车是其子类。
2)产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。如宝马车工厂生产的宝马轿车,宝马SUV,宝马卡车,宝马轿车位于轿车产品等级结构中,宝马卡车位于卡车产品等级结构中。宝马轿车和宝马卡车就构成一个产品族。
2.工厂方法
描述:工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。在同一等级结构中,支持增加任意产品。
理解几个关键点
1)抽象产品角色:它一般是具体产品继承的父类或要实现的接口。
2)具体产品角色:工厂类创建的对象就是该角色的实例。
3)抽象工厂角色:它一般是具体工厂角色继承的父类或要实现的接口。
3)具体工厂角色:含有一定的业务逻辑和判断逻辑。
代码实例:
/**
* 抽象产品定义
* */
public interface Car {
/**
* 只要能跑就行
* */
void run();
}
/**
* 具体产品(奔驰)定义:实现抽象产品
* */
public class BenzCar implements Car{
@Override
public void run() {
System.out.println("我是高级轿车Benz,我会跑");
}
}
/**
* 具体产品(宝马)定义:实现抽象产品
* */
public class BMWCar implements Car{
@Override
public void run() {
System.out.println("我是高级轿车BMW,我会跑");
}
}
/**
* 定义一个抽象工厂角色(接口)
* */
public interface IFactory {
/**
* 生产各种品牌车
* */
Car createCar();
}
/**
* 定义具体的工厂(生产宝马)
* */
public class BMWFactory implements IFactory{
@Override
public Car createCar() {
return new BMWCar();
}
}
/**
* 定义具体的工厂(生产奔驰)
* */
public class BenzFactory implements IFactory{
@Override
public Car createCar() {
return new BenzCar();
}
}
public class Client {
public static void main(String[] args) {
/**
* 客户:我要一辆宝马车
* 宝马工厂:好的,马上给你
**/
IFactory bmwFactory = new BMWFactory();
Car bmwCar = bmwFactory.createCar();
bmwCar.run();
/**
* 客户:我要一辆宝马车
* 奔驰工厂:好的,马上给你
**/
IFactory benzFactory = new BenzFactory();
Car benzCar = benzFactory.createCar();
benzCar.run();
}
}
3.抽象工厂
描述:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。
理解几个关键点
1)抽象产品角色:它一般是具体产品继承的父类或要实现的接口。
2)具体产品角色:工厂类创建的对象就是该角色的实例。
3)抽象工厂角色:它一般是具体工厂角色继承的父类或要实现的接口。
3)具体工厂角色:含有一定的业务逻辑和判断逻辑。
代码实例:
/**
* 定义抽象产品:轿车
* */
public interface Sedan {
void sedanName();
}
/**
* 定义抽象产品:卡车
* */
public interface Truck {
void truckName();
}
/**
* 定义具体产品:宝马轿车
* */
public class BMWSedan implements Sedan{
@Override
public void sedanName() {
System.out.println("我是宝马轿车");
}
}
/**
* 定义具体产品:奔驰轿车
* */
public class BenzSedan implements Sedan{
@Override
public void sedanName() {
System.out.println("我是奔驰轿车");
}
}
/**
* 定义具体产品:宝马卡车
* */
public class BMWTruck implements Truck{
@Override
public void truckName() {
System.out.println("我是宝马卡车");
}
}
/**
* 定义具体产品:奔驰卡车
* */
public class BenzTruck implements Truck{
@Override
public void truckName() {
System.out.println("我是奔驰卡车");
}
}
/**
* 定义抽象工厂
* */
public interface IFactory {
/**
* 生产轿车
* */
Sedan createSedan();
/**
* 生产卡车
* */
Truck createTruck();
}
/**
* 定义具体工厂:宝马车生产工厂
* */
public class BMWFactory implements IFactory{
@Override
public Sedan createSedan() {
return new BMWSedan();
}
@Override
public Truck createTruck() {
return new BMWTruck();
}
}
/**
* 定义具体工厂:奔驰车生产工厂
* */
public class BenzFactory implements IFactory{
@Override
public Sedan createSedan() {
return new BenzSedan();
}
@Override
public Truck createTruck() {
return new BenzTruck();
}
}
public class Client {
public static void main(String[] args) {
/**
* 客户:我要一辆宝马轿车、一辆宝马卡车
* 宝马工厂:好的,马上给你
**/
IFactory bmwFactory = new BMWFactory();
Sedan bmwSedan = bmwFactory.createSedan();
bmwSedan.sedanName();
Truck bmwTruck = bmwFactory.createTruck();
bmwTruck.truckName();
}
}
输出结果:
我是宝马轿车
我是宝马卡车
4.总结
简单工厂模式:所有的业务逻辑判断都在工厂类中,后期每增加一个新产品,都需要修改工厂类,这种设计模式不符合开闭原则(对扩展开发,对修改封闭),不利于扩展。
工厂方法模式:是对简单工厂模式的进一步解耦,因为在工厂模式中是一个子类产品对应一个工厂类,而这些工厂类都是实现了抽象工厂类。这就相当于把原本会因为业务庞大的简单工厂类,拆分成一个个的工厂类(把业务逻辑部分放到了客户端去做),这样代码都不会耦合在同一个类中了,符合了开闭原则。但工厂方法模式的缺点是每增加一个产品类,就需要增加一个对应的工厂类,增加了额外的开发量。
抽象工厂模式:是工厂方法模式的进一步延伸,由于它提供了功能更为强大的工厂类并且具备较好的可扩展性。
主要优点如下:
(1) 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
(2) 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
(3) 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。
主要缺点如下:
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。