目录
前言
从大三实习开始算起来,如今也已经过去了一年的时间了。为了提升自己的技术,为公司创造出跟多的价值(多搞钱)。开始更加重视自己的代码质量,看看网络上的课程来提升自己。
想要提升代码的质量,设计模式是一个绕不开的话题。在我刚刚开始学习java的时候就听说过设计模式这玩意,我那会就在思考为什么要学设计模式?设计模式会带来哪些好处?
- 提升自己查看源码的能力
- 可重用代码
- 使代码更容易被他人理解、保证了代码可靠性
- 为后面的职场道路打下基础
正文
这次主要介绍的工厂模式,工厂模式在各个领域的应用都是非常普遍的一种设计模式。
工程模式主要可以分为三种
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
本文将围绕这三个模式进行展开在业务中的应具体用场景与具体的实现。
简单工厂模式
工厂模式主要是用于对实现逻辑的封装,并且通过对公共的接口提供对象的实列化的服务。
简单工厂模式 (Simple Factory) 又叫静态工厂方法(Static Factory Method)模式。简单工厂模式通常是定义一个工厂类,这个类可以根据不同变量返回不同类的产品实例。
举一个电商业务中的例子
简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可。
- 工厂类代码:
public class SimpleProductFactory {
// 根据type判断类型,实例化并返回对应对象
public Product createProduct(String type) {
Product product = null;
if("ProductA".equals(type)) {
product = new ProductA();
} else if("ProductB".equals(type)) {
product = new ProductB();
}
return product;
}
}
工厂处理创建对象的细节,一旦有了工厂,后期如果需要对象直接从工厂中获取即可。通过上面的示例代码,就可以根据不同的传入类型返回产生不同的类。
但是这种方法,并不完善。每增加一个类型就要去修改if,else中的参数。违背了开闭性的原则。
针对这一问题可以通过反射+简单工厂模式解决。反射机制指的是在程序运行时能够过去自身信息。它可以在运行时构造一个类的对象,也可以在运行时判断一个类所具有的成员变量和方法。通过反射机制可以轻松的解决简单工厂模式存在的问题,不需要修改类型中的if-else就可以增加类型。
Class.forName(className).getDeclaredConstructor().newInstance();
上述这段反射代码的基本意思也非常容易理解,通过getDeclaredConstructor()选择一个构造方法,newInstance()负责创建实例。
interface Product {
void send();
}
class ProductA implements Product {
@Override
public void create() {
System.out.println("商品A创建成功");
}
}
class ProductB implements Product {
@Override
public void create() {
System.out.println("商品B创建成功");
}
}
class productFactory{
public productFactory(){}
public static Product getInstance(String className) throws Exception {
Product product = null;
instance = (Product)
Class.forName(className).getDeclaredConstructor().newInstance();
return product;
}
}
public class Client{
public static void main(String[] args) throws Exception {
Product productA = productFactory.getInstance("productA");
productA.create();
Product productB = productFactory.getInstance("productB");
productB.create();
}
}
如此一来便通过反射实现了简单工厂模式。我们只需要在外部写好我们要创建商品的类,给工厂传递我们想创建的类。简单工厂就可以通过反射创建出我们想要的类,不需要修改if-else,实现软件设计的开闭性原则。
工厂方法模式
工厂方法模式是对于简单工厂模式的进一步抽象。工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。在使用时,用于只需知道产品对应的具体工厂,关注具体的创建过程,甚至不需要知道具体产品类的类名,当我们选择哪个具体工厂时,就已经决定了实际创建的产品是哪个了。
缺点在于,这样做会使得系统中类的个数成倍增加,增加了系统的复杂度,同时也增加了系统具体类的依赖。
具体代码demo:
工厂类demo:
//抽象工厂类
interface AbstractFactory{
Product CreateProduct();
}
//具体工厂A
public class ProductAFactory implements AbstractFactory{
@Override
public Product CreateProduct() {
return new ProductA();
}
}
//具体工厂B
public class ProductBFactory implements AbstractFactory{
@Override
public Product CreateProduct() {
return new ProductB();
}
}
产品类demo:
//抽象产品类
abstract class Product {
public CreateProduct(){}
}
//具体产品类A
public class ProductA extends Product{
public CreateProduct() {
System.out.println("制造ProductA");
}
}
//具体产品类B
public class ProductB extends Product{
public CreateProduct(){
System.out.println("制造ProductB");
}
}
客户类demo:
public class Customer {
public static void main(String[] args) {
ProductAFactory productAFactory = new ProductAFactory();
ProductA productA = productAFactory.CreateProduct();
ProductBFactory productBFactory = new ProductBFactory();
ProductB productB = productBFactory.CreateProduct();
}
}
在demo中包含了以下几个名词,抽象工厂、具体工厂、抽象产品、具体产品,它们具体的含义如下:
- 抽象工厂:是整个抽象工厂方法模式的核心,是具体工厂角色必须实现的接口。
- 具体工厂 :继承了抽象工厂,并实现里面的方法,包含具体的业务逻辑。
- 抽象产品 :是具体产品继承的父类或实现的接口,在 Java 中一般由抽象类或者接口来实现。
- 具体产品 :具体工厂角色所创建的对象就是此角色的实例,具体产品继承抽象产品。
在业务逻辑不是很复杂只需要new创建实例的时候,可以使用简单工厂模式。在业务逻辑复杂需要组合其他对象或者做各种初始化操作的时候比较推荐使用工厂方法模式来实现。
抽象工厂模式
在工厂方法模式中,我们使用一个工厂创建一个产品,一个具体工厂对应一个具体产品,但有时候我们需要一个工厂能够提供多个产品对象,而不是单一的对象,这个时候我们就需要使用抽象工厂模式。
抽象工厂模式主要用于创建相关对象的家族。当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用同一个产品族中的对象;并且通过隔离具体类的生成,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
其实抽象工厂模式,就是在工厂方法模式的基础上的延伸。工厂方法类中只有一个抽象方法,而抽象工厂 则是让一个工厂负责创建多个不同类型的对象。这里就不写demo了,无非就是在工厂方法模式的基础上,增加抽象类以及实现类。并且在抽象工厂中加入跟多类型抽象类的实现方法。