1.概述
设计模式中,工厂模式和抽象工厂模式都是创建型模式的代表,它提供了一种创建对象的最佳方式,是JAVA中较为常用的一种创建对象的模式。本文将分析工厂模式原理,并使用案例进行讲解。
2.工厂模式
2.1 工厂模式
工厂模式是由一个工厂对象决定创建出哪一种产品类的实例,简单工厂模式定义了一个创建对象的类,由这个类来封装实例化对象的行为,简单工厂模式是工厂模式中最简单实用的模式。
案例:有一个抽象类Car,内部有一些抽象方法,BenzCar和BMWCar都是Car的具体实现类,CarFactory可以根据传入type来选择创建BenzCar或者BMWCar,类图如下:
编码如下:
public abstract class Car {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
private String name;
private String color;
public void prepareCar() {
}
public void makeCar() {
}
public void testCar() {
}
public void haveCar() {
}
}
public class BMWCar extends Car {
public BMWCar() {
this.setName("宝马");
this.setColor("Red");
}
public void prepareCar() {
System.out.println("准备" + getColor() + ":" + getName() + "车造车材料......");
}
public void makeCar() {
System.out.println("准备" + getColor() + ":" + getName() + "车造车材料......");
}
public void testCar() {
System.out.println("测试" + getColor() + ":" + getName() + "车性能......");
}
public String getName() {
return super.getName();
}
public void haveCar() {
prepareCar();
makeCar();
testCar();
System.out.println("恭喜有了一辆新车" + ":" + getName());
}
}
public class BenzCar extends Car {
public BenzCar() {
this.setName("奔驰");
this.setColor("White");
}
public void prepareCar() {
System.out.println("准备" + getColor() + ":" + getName() + "车造车材料......");
}
public void makeCar() {
System.out.println("准备" + getColor() + ":" + getName() + "车造车材料......");
}
public void testCar() {
System.out.println("测试" + getColor() + ":" + getName() + "车性能......");
}
public String getName() {
return super.getName();
}
public void haveCar() {
prepareCar();
makeCar();
testCar();
System.out.println("恭喜有了一辆新车" + ":" + getName());
}
}
public class CarFactory {
public Car createCar(String type) {
if (type.equals("benz")) {
return new BenzCar();
} else if (type.equals("bmw")) {
return new BMWCar();
} else
return null;
}
public static void main(String[] args) {
CarFactory carFactory = new CarFactory();
Car benz = carFactory.createCar("benz");
benz.haveCar();
Car bmw = carFactory.createCar("bmw");
bmw.haveCar();
}
}
工厂模式优势:
(1)一个调用者想创建一个对象,只要知道其名称就可以了;
(2)扩展性较高,如果想增加一个产品,只需添加一个工厂类即可;
(3)屏蔽了产品的具体实现,调用者之关系创建对象的接口。
工厂模式缺点:
每次增加一个产品时,都需要增加一个具体类和对象工厂的实现,使得系统中的类个数大量增加,工厂中创建对象的代码不断增加,一定程度上增加了系统复杂度。
2.2 抽象工厂模式
定义:抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂,该超级工厂又称为其它工厂的工厂。 在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。抽象工厂模式的本质是抽象顶层接口(负责相关工厂的创建),工厂负责生产产品所需要的所有成分,当需要制定成分,调用指定工厂类生产,最后进行组合,形成完整的产品。抽象工厂的使用场景在于:系统的产品有多个的产品族, 而系统只消费其中某一族的产品。
案例:汽车工厂CarFactory负责生产汽车,汽车需要引擎和轮胎这些东西组合而成。引擎工厂Enginefactory负责生产不同的引擎,TireFactory负责生产不同的轮胎。
类图如下:
代码如下:
public abstract class CarFactory {
public abstract Engine createEngine(String type);
public abstract Tire createTire(String type);
}
public class EngineFactory extends CarFactory {
public Engine createEngine(String type) {
if (type.equals("bmw")) {
return new BMWEngine();
}else if (type.equals("benz")) {
return new BenzEngine();
}
return null;
}
public Tire createTire(String type) {
return null;
}
}
public class TireFactory extends CarFactory{
public Engine createEngine(String type) {
return null;
}
public Tire createTire(String type){
if (type.equals("bmw")) {
return new BMWTire();
}else if (type.equals("benz")) {
return new BenzTire();
}
return null;
}
}
public class BenzEngine extends Engine {
public void turnOn(){
System.out.println("启动引擎");
System.out.println("Benz引擎启动");
}
public void turnOff(){
System.out.println("关闭引擎");
System.out.println("Benz引擎关闭");
}
}
public class BMWEngine extends Engine {
public void turnOn() {
System.out.println("启动引擎");
System.out.println("BMW引擎启动");
}
public void turnOff() {
System.out.println("关闭引擎");
System.out.println("BMW引擎关闭");
}
}
public class BenzTire extends Tire {
public void productTire() {
System.out.println("生产轮胎");
System.out.println("BMW 轮胎生产完成");
}
public void testTire() {
System.out.println("测试轮胎");
System.out.println("BMW 轮胎测试完成");
}
}
public class BMWTire extends Tire {
public void productTire() {
System.out.println("生产轮胎");
System.out.println("BMW 轮胎生产完成");
}
public void testTire() {
System.out.println("测试轮胎");
System.out.println("BMW 轮胎测试完成");
}
}
public abstract class Engine {
private String name;
public void turnOn(){
System.out.println("启动引擎");
}
public void turnOff(){
System.out.println("关闭引擎");
}
}
public abstract class Tire {
private String name;
public void productTire() {
System.out.println("生产轮胎");
}
public void testTire() {
System.out.println("测试轮胎");
}
}
public class FactoryProducer {
public static CarFactory getFactory(String choice) {
if (choice.equalsIgnoreCase("tire")) {
return new TireFactory();
} else if (choice.equalsIgnoreCase("engine")) {
return new EngineFactory();
}
return null;
}
}
public class Test {
public static void main(String[] args) {
CarFactory tire = FactoryProducer.getFactory("tire");
Tire bmw = tire.createTire("bmw");
bmw.productTire();
CarFactory engine = FactoryProducer.getFactory("engine");
Engine benz = engine.createEngine("benz");
benz.turnOn();
}
}
工厂模式和抽象工厂模式都是创建型模式的代表,唯一区别在于需要根据场景复杂程度来决定使用场景,当系统内产品数量相对较少,且呈复杂增长的趋势较小,应选择工厂模式;若系统内产品相对较为复杂,且对象增长趋势难以确定,应选择抽象工厂模式进行产品抽象,方便应对复杂变化。
抽象工厂模式优点: 保证多个对象能协同工作,同时保证获取到的产品属于同一个产品族;
抽象工厂模式缺点:扩展相对较为困难,当新增产品时,需要修改抽象工厂类,同时还有添加具体产品获取代码,在一定程度上违反开闭原则。
3.小结
1.工厂模式和抽象工厂模式都是创建型模式;
2.模式的使用都是基于场景进行选择,没有银弹。
4.参考文献
1.《设计模式-可复用面向对象软件的基础》-Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides
2.《可复用物联网Web3D框架的设计与实现》-程亮(知网)
3.https://www.bilibili.com/video/BV1G4411c7N4-尚硅谷设计模式