设计模式之工厂模式的理解
工厂模式是一种创建型模式,相信工作中大家都会接触过一些,下面将详细讨论一下
讲解流程主要是:UML类图 + 代码实现 + 优势与劣势
一、简单工厂模式:
创建对象时做简单的封装
1、UML类图:
UML类图分析:
1、创建一个产品接口 (AbstractProduct)
2、产品的具体实现类(Product1 和 Product2)
3、工厂类 (Factory)
2、代码实现:
// 产品接口
public interface AbstractProduct {
doSomething();
}
// 产品具体实现类 Product1
public class Product1 implements AbstractProduct {
@override
public doSomething() {
System.out.println("Product1");
}
}
// 产品具体实现类 Product2
public class Product2 implements AbstractProduct {
@override
public doSomething() {
System.out.println("Product2");
}
}
// 工厂类:
public class Factory {
public AbstractProduct do(String productType) {
if (productType.equals("Product1")) {
return new Product1();
} else if (productType.equals("Product2")) {
return new Product2();
}
}
}
3、分析:简单工厂模式实际就是所有产品类都交给一个具体的工厂进行实现,主要的好处是 :
传统的方式是在使用对象的时候通过new方法进行创建,通过简单工厂模式就可以在使用时通过工厂创建
(将对象创建与对象使用进行解耦)
但是当引入新的产品Product3时,就需要添加一个Product3实现类,并且修改原本的工厂类,如下:
// 新增产品具体实现类 Product3
public class Product2 implements AbstractProduct {
@override
public doSomething() {
System.out.println("Product2");
}
}
// 修改工厂类为:
public class Factory {
public AbstractProduct do(String productType) {
if (productType.equals("Product1")) {
return new Product1();
} else if (productType.equals("Product2")) {
return new Product2();
} else if (productType.equals("Product3")) {
return new Product3();
}
}
}
在面向对象开发中有一个很重要的原则:开闭原则
概念:程序扩展是开放的,程序修改是封闭的,扩展优于修改
在新增产品时,很明显的,我们要修改原有的工厂代码,违背了开闭原则。
二、工厂方法模式
应对要新增产品带来开闭原则的问题,这里引入了工厂方法模式:
将工厂类抽象,由多个产品对应一个工厂 ----> 多个产品对应多个工厂
1、UML类图:
UML类图分析:
1、 创建一个产品接口: AbStractProduct
2、 创建产品的具体实现类: Product1 、 Product2
3、 创建一个工厂接口 : AbstractFactory
4、 创建工厂的具体实现类 : ConcreteFactory1 、ConcreteFactory2
2、代码实现:
// 产品接口
public interface AbstractProduct {
doSomething();
}
// 产品具体实现类 Product1
public class Product1 implements AbstractProduct {
@override
public doSomething() {
System.out.println("Product1");
}
}
// 产品具体实现类 Product2
public class Product2 implements AbstractProduct {
@override
public doSomething() {
System.out.println("Product2");
}
}
// 工厂接口:AbstractFactory
public interface AbstractFactory {
public AbstractProduct do();
}
// 针对 Product1 的的工厂类
public ConcreteFactory1 implements AbstractFactory {
public AbstractProduct do() {
return new Product1();
}
}
// 针对 Product2 的工厂类
public ConcreteFactory1 implements AbstractFactory {
public AbstractProduct do() {
return new Product2();
}
}
3、分析:
主要优势:
在新增一个产品类时,需要新增一个产品具体实现类和具体产品对应的工厂类,包含简单工厂模式的解耦优点,也实现扩展由于修改,没有违背开闭原则
三、抽象工厂模式
引入抽象工厂模式时,不能说这个模式就一定高大上,主要还是看使用场景
与工厂方法模式相比,抽象工厂模式主要是打破了工厂与产品一对一,使得具体工厂可以创造一个大类
1、UML类图
UML类图分析:与工厂方法模式对比
1、引入了新的产品维度(产品AB),即在原本的产品维度(12)基础上加上了产品维度(AB)
2、创建俩个大类产品接口 AbstractProductA 和 AbstractProductB
3、编写产品的具体实现类: ProductA1、ProductA2、ProductB1、ProductB2
4、针对大类产品接口,编写大类工厂接口 AbstractFactory
5、编写俩个大类工厂类: ConcreteFactory1、 ConcreteFactory2
代码实现:
// 大类产品接口 AbstractProductA
public interface AbstractProductA {
doSomething();
}
// 大类产品接口 AbstractProductB
public interface AbstractProductB {
doSomething();
}
// 产品具体实现类 ProductA1
public class ProductA1 implements AbstractProductA {
@override
public doSomething() {
System.out.println("ProductA1");
}
}
// 产品具体实现类 ProductA2
public class ProductA2 implements AbstractProductA {
@override
public doSomething() {
System.out.println("ProductA2");
}
}
// 产品具体实现类 ProductB1
public class ProductB1 implements AbstractProductB {
@override
public doSomething() {
System.out.println("Product2");
}
}
// 产品具体实现类 ProductB2
public class ProductB2 implements AbstractProductB {
@override
public doSomething() {
System.out.println("ProductB2");
}
}
// 工厂接口:AbstractFactory
public interface AbstractFactory {
public AbstractProduct createProductA();
public AbstractProduct createProductB();
}
// 针对 Product1 的的工厂类
public ConcreteFactory1 implements AbstractFactory {
public AbstractProduct createProductA() {
return new ProductA1();
}
public AbstractProduct createProductB() {
return new ProductB1();
}
}
// 针对 Product2 的工厂类
public ConcreteFactory2 implements AbstractFactory {
public AbstractProduct createProductA() {
return new ProductA2();
}
public AbstractProduct createProductB() {
return new ProductB2();
}
}
分析:
当新增一个产品维度时,使用抽象工厂模式可以减少创建工厂类,但是当在引入一个新的产品ProductC时,就需要改变工厂类的方法,又会违背开闭原则 。
当引入ProductC时:
// 改变 Product1 的的工厂类
public ConcreteFactory1 implements AbstractFactory {
public AbstractProduct createProductA() {
return new ProductA1();
}
public AbstractProduct createProductB() {
return new ProductB1();
}
public AbstractProduct createProductB() {
return new ProductC1();
}
}
// 改变 Product2 的的工厂类
public ConcreteFactory2 implements AbstractFactory {
public AbstractProduct createProductA() {
return new ProductA2();
}
public AbstractProduct createProductB() {
return new ProductB2();
}
public AbstractProduct createProductB() {
return new ProductC2();
}
}
总结:上面介绍的三种工厂模式有各自的应用场景,实际应用时能解决问题满足需求即可,可灵活变通,无所谓高级与低级。
此外无论哪种模式,由于可能封装了大量对象和工厂创建,新加产品需要修改已定义好的工厂相关的类,因此对于产品和工厂的扩展不太友好,利弊需要权衡一下。
实际应用1
集合类的Collection:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YXtuYgex-1604249312752)(C:\Users\晓\AppData\Roaming\Typora\typora-user-images\1604243974896.png)]
blic AbstractProduct createProductB() {
return new ProductC2();
}
}
总结:上面介绍的三种工厂模式有各自的应用场景,实际应用时能解决问题满足需求即可,可灵活变通,无所谓高级与低级。
此外无论哪种模式,由于可能封装了大量对象和工厂创建,新加产品需要修改已定义好的工厂相关的类,因此对于产品和工厂的扩展不太友好,利弊需要权衡一下。
##### 实际应用1
集合类的Collection:
