前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【设计模式】-创建型模式-第2章第2讲-【工厂模式】

【设计模式】-创建型模式-第2章第2讲-【工厂模式】

作者头像
跟着飞哥学编程
发布2022-12-02 15:48:59
2550
发布2022-12-02 15:48:59
举报

目录

场景描叙:

1、简单工厂模式

1.1、静态工厂模式

1.2、 使用反射机制进行类注册的简单工厂模式

1.3、使用 newInstance 方法进行类注册的简单工厂模式

2、工厂方法模式

2.1、案例场景:假设有一个汽车工厂,目前只生产两种车型,小型跑车和大型家用车。顾客决定买小还是大型。

2.2、这时候,我们需要拓展业务,增加卡车类的生产,那我们可以创建一个卡车工厂(TruckFactory)。

3、抽象工厂模式

结尾:


场景描叙:

比如小汽车(Car)和 卡车 (Truck)都属于车辆(Vehicle),那我们实例化对象时,就需要分别实例化两个对象。

Vehicle vehicle = new Car();

Vehicle vehicle = new Truck();

以上的代码就存在两个问题:

1)类应该保持对扩展开放,对修改关闭(开闭原则);

每增加新的类造成主要代码修改会打破开闭原则。

2)每个类应该只有一个发生变化的原因(单一职责原则);

而主类除了自身固有功能还要负责实例化 vehicle 对象,这种行为打破了单一职责原则。

所以这种情况下就需要一种更好的设计方案。我们可以增加一个新类来负责实例化  vehicle 对象,称之为简单工厂模式

1、简单工厂模式

工厂模式用于实现逻辑的封装,并通过公共接口提供对象的实例化服务,在添加新类时只需要做少量修改即可。

通俗点儿就是封装一个抽象工厂类,实现对象的实例化。

简单工厂的实现描叙如 图 1-1 所示:

图 1-1

1.1、静态工厂模式

我们创建一个抽象 Vehicle 类和继承自它的三个具体类:Bike、Car 和 Truck

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.simpleFactory;

public abstract class Vehicle {

}
代码语言:javascript
复制
package com.zhaoyanfei.designpattern.simpleFactory;

public class Bike extends Vehicle {

}
代码语言:javascript
复制
package com.zhaoyanfei.designpattern.simpleFactory;

public class Car extends Vehicle {

}
代码语言:javascript
复制
package com.zhaoyanfei.designpattern.simpleFactory;

public class Truck extends Vehicle {

}

 这里,我们写一个简单的工厂类用来创建 Vehicle 实例。工厂类(静态工厂类)代码如下:

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.simpleFactory;

public class VehicleFactory {
	
	public enum VehicleType
	{
		Bike,Car,Truck;
	}
	public static Vehicle create(VehicleType type) {
		if(type.equals(VehicleType.Bike)) 
		return new Bike();
		if(type.equals(VehicleType.Car)) 
		return new Car();
		if(type.equals(VehicleType.Truck)) 
		return new Truck();
		else return null;
	}
}

通过上面代码示例,我们可以看到工厂类逻辑非常简单,只负责抽象类 (Vehicle) 类的实例化,符合单一职责原则,用户只需要调用 Vehicle 接口,这么做可以减少耦合,符合依赖倒置原则;但是增加一个新的 Vehicle 类时,需要对 VehicleFactory 工厂类进行修改,就打破了开闭原则。

我们可以改进这种简单工厂模式,使得注册的新类在使用时才被实例化,从而保证其对扩展开放,对修改关闭。

具体实现方式有以下两种:

1)使用反射机制注册产品类对象和实例化。

2)注册产品对象并向每个产品添加 newInstanse 方法,该方法返回与自身类型相同的新实例。

1.2、 使用反射机制进行类注册的简单工厂模式

这里,我们在工厂类中需要用 map 对象来保存产品 ID 及其对应的类:

 然后增加一个注册新 Vehicle 类的方法

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.simpleFactory;

import java.util.HashMap;
import java.util.Map;

public class VehicleFactory {
	
	public enum VehicleType
	{
		Bike,Car,Truck;
	}
	public static Vehicle create(VehicleType type) {
		if(type.equals(VehicleType.Bike)) 
		return new Bike();
		if(type.equals(VehicleType.Car)) 
		return new Car();
		if(type.equals(VehicleType.Truck)) 
		return new Truck();
		else return null;
	}
	//工厂类中需要用 map 对象来保存产品 ID 及其对应的类
	private Map<String,Class> registeredProducts = new HashMap<String,Class>();
	//然后增加一个注册新 Vehicle 类的方法
	public void registerVehicle(String vehicleId,Class vehicelClass) {
		registeredProducts.put(vehicleId, vehicelClass);
	}
	//构造方法如下所示:
	public Vehicle createVehicle(String type) throws InstantiationException, IllegalAccessException {
		Class productClass = registeredProducts.get(type);
		return (Vehicle) productClass.newInstance();
	}
}

上面代码中,我们可以看到反射实例化对象时,会有异常抛出。所以在某些情况下,反射机制并不适用。另外,反射机制也会降低程序的运行效率,在对性能要求很高的场景下应该避免使用这种机制。

1.3、使用 newInstance 方法进行类注册的简单工厂模式

前面我们用的反射机制来实现新 Vehicle 类的实例化。如果要避免使用反射机制,可以使用注册新 Vehicle 类的类似工厂类,不再将类添加到 map 对象中,而是将要注册的每种对象实例添加其中。每个产品类都能够创建自己的实例。

1)首先在基类 Vehicle 中添加一个抽象方法:

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.simpleFactory;

public abstract class Vehicle {

	abstract public Vehicle newInstance();

}

2)此时,大家都知道,子类必须实现基类中声明的抽象方法:

 Bike、Car 和 Truck 都需要实现 newInstance()方法,每个产品类创建自己的实例。

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.simpleFactory;

public class Bike extends Vehicle {

	@Override
	public Vehicle newInstance() {
		return new Bike();
	}

}

3)在工厂类中,更改 map 用于保存对象的 ID 及其对应的 Vehicle 对象:

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.simpleFactory;

import java.util.HashMap;
import java.util.Map;

public class VehicleFactory {
	
	public enum VehicleType
	{
		Bike,Car,Truck;
	}
	public static Vehicle create(VehicleType type) {
		if(type.equals(VehicleType.Bike)) 
		return new Bike();
		if(type.equals(VehicleType.Car)) 
		return new Car();
		if(type.equals(VehicleType.Truck)) 
		return new Truck();
		else return null;
	}
	/**
	 * 反射机制
	 */
	//工厂类中需要用 map 对象来保存产品 ID 及其对应的类
//	private Map<String,Class> registeredProducts = new HashMap<String,Class>();
//	//然后增加一个注册新 Vehicle 类的方法
//	public void registerVehicle(String vehicleId,Class vehicelClass) {
//		registeredProducts.put(vehicleId, vehicelClass);
//	}
//	//构造方法如下所示:
//	public Vehicle createVehicle(String type) throws InstantiationException, IllegalAccessException {
//		Class productClass = registeredProducts.get(type);
//		return (Vehicle) productClass.newInstance();
//	}
	
	/**
	 * 注册产品对象,并向每个产品添加 newInstance 方法,该方法返回与自身类型相同的新实例
	 */
	private Map<String,Vehicle> registeredProducts = new HashMap<String,Vehicle>();
	//然后增加一个注册新 Vehicle 类的方法
	public void registerVehicle(String vehicleId,Vehicle vehicle) {
		registeredProducts.put(vehicleId, vehicle);
	}
	//构造方法如下所示:
	public Vehicle createVehicle(String type) {
		Vehicle productClass = registeredProducts.get(type);
		return productClass.newInstance();
	}
}

2、工厂方法模式

工厂方法模式(FACTORY METHOD)是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽象工厂;具体工厂;抽象产品;具体产品

工厂方法模式是在静态工厂模式上的改进。工厂类被抽象化,用于实例化特定产品类的代码被转移到实现抽象方法的子类中。这样就不需要修改就可以扩展工厂类。实现如 图2-1:

图2-1 

2.1、案例场景:假设有一个汽车工厂,目前只生产两种车型,小型跑车和大型家用车。顾客决定买小还是大型。

1)首先我们需要创建一个 Vehicle 类和两个子类,子类分别为 SportCarSedanCar

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.factorymethod;

public class Vehicle {
	String color;
	
	public void setColor(String color) {
		this.color = color;
	}

}
代码语言:javascript
复制
package com.zhaoyanfei.designpattern.factorymethod;

public class SportCar extends Vehicle {

}
代码语言:javascript
复制
package com.zhaoyanfei.designpattern.factorymethod;

public class SedanCar extends Vehicle {

}

2)创建抽象工厂类,此类中不包含任何创建新实例的代码:

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.factorymethod;


public abstract class VehicleFactory {

	protected  abstract Vehicle createVehicle(String item);
	
	public Vehicle orderVehicle(String size,String color) {
		Vehicle vehicle = createVehicle(size);
		vehicle.setColor(color);
		return vehicle;
	}
}

3)增加汽车实例化代码,我们创建 VehicleFactory 的子类  

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.factorymethod;

public class CarFactory extends VehicleFactory {

	@Override
	protected Vehicle createVehicle(String size) {
		if(size.equals("small")) {
			return new SportCar();
		}else if(size.equals("large")) {
			return new SedanCar();
		}else {
			return null;
		}
	}
	
}

 4)客户端,我们只需要创建工厂类并创建订单:

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.factorymethod;

public class TestMethodFactory {

	public static void main(String[] args) {
		VehicleFactory carFactory = new CarFactory();
		Vehicle orderVehicle = carFactory.orderVehicle("large", "green");
		System.out.println("类名:"+orderVehicle.getClass().getName()+"颜色:"+orderVehicle.color);
	}
}

 运行后可以看到如下输出:

2.2、这时候,我们需要拓展业务,增加卡车类的生产,那我们可以创建一个卡车工厂(TruckFactory)。

代码语言:javascript
复制
package com.zhaoyanfei.designpattern.factorymethod;

public class TruckFactory extends VehicleFactory {

	@Override
	protected Vehicle createVehicle(String size) {
		if(size.equals("small")) {
			return new SmallTruck();
		}else if(size.equals("large")) {
			return new LargeTruck();
		}else {
			return null;
		}
	}
	
}

 我们就可以这样来创建卡车订单了:

代码语言:javascript
复制
VehicleFactory truckFactory = new TruckFactory();
Vehicle orderVehicle = truckFactory.orderVehicle("large", "blue");

3、抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)是工厂方法模式的扩展版本。它不再是创建单一类型的对象,而是创建一系列相关联的对象,如果说工厂方法模式中只包含一个抽象产品类,那么抽象工厂模式则包含多个抽象产品类。所以说工厂方法模式只是抽象工厂模式的一种特例

抽象工厂设计模式的实现如图 3-1 所示:

 图 3-1

抽象工厂模式由以下类组成:

  • AbstractFactory (抽象工厂类):抽象类,用于声明创建不同类型产品的方法。它针对不同的抽象产品类都有对应的创建方法。
  • ConcreteFactory (具体工厂类):具体类,用于实现抽象工厂基类中声明的方法。针对每个系列的产品都有一个对应的具体工厂类。
  • AbstractProduct(抽象产品类):对象所需要的基本接口或类。一簇相关产品类由来自不同层级的相似产品类组成。ProductA1 和 ProductB1 来自第一个类簇,由 ConcreteFactory1 实例化。ProductA2 和 ProductB2 来自第二个类簇,由 ConcreteFactory2 实例化。

结尾:

工厂的模式的核心就是右工厂类来负责合适对象的创建。如果工厂类很复杂,比如同时服务于多种类型的对象或工厂,也可以根据前面内容修改相应的代码。

下一节,分享建造者模式…… 

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 场景描叙:
  • 1、简单工厂模式
    • 1.1、静态工厂模式
      • 1.2、 使用反射机制进行类注册的简单工厂模式
        • 1.3、使用 newInstance 方法进行类注册的简单工厂模式
        • 2、工厂方法模式
          • 2.1、案例场景:假设有一个汽车工厂,目前只生产两种车型,小型跑车和大型家用车。顾客决定买小还是大型。
            • 2.2、这时候,我们需要拓展业务,增加卡车类的生产,那我们可以创建一个卡车工厂(TruckFactory)。
            • 3、抽象工厂模式
            • 结尾:
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档