前言
很多框架中都设计到设计模式,其中工厂模式最常用,为了日后能更好研究框架源码,或者对于小白的我来说至少能读懂框架源码。掌握基本的设计模式是必须的。所以在这里做一个粗浅的认识总结,其中可能会有很多的瑕疵,希望大家多多包涵,此外其中的UML都是自己画的,自我感觉不太很正规。
概念
以工厂方法模式(Factory Method Model
)UML说明相关概念
角色说明:
- 抽象工厂角色
AbstractFactory
:工厂方法模式的核心,它与应用程序无关,其中主要规定返回的抽象产品,是具体工厂角色必须实现的接口或者必须继承的父类,由子类实现返回的具体产品。 - 具体工厂角色
ConcreteFactoryA/B
:实现或继承自抽象工厂角色,含有和具体业务逻辑有关的代码。创建对应的具体产品的对象。 - 抽象产品角色
Product
:是所有具体产品角色的父类,它负责描述所有产品实例所共有的公共接口。 - 具体产品角色
ConcreteProductA/B
:继承或者实现自抽象产品角色,一般为多个。工厂类返回的都是该角色的某一具体产品。
应用实例:
- Hibernate换数据库只需要换方言和驱动就可以,不需要关心是怎么生成相关的类。
- 我们去饭店点餐,只需要按照菜单选择好吃好看的报上名字就可以,而不需要关心后台厨师(工厂)是怎么炒菜的。
- 比如某位女生的衣柜里存在商务女装、时尚女装、休闲女装、男朋友买的套装(谁叫女生的衣服多呢,我就拿这个比喻了,哈哈)这些也都是成套存在的,即可以理解为一系列具体产品。某一天她要去约会,那么她选择的是男朋友买的套装出门,那么这个套装有上衣(某个具体产品),裤子(某个具体产品)。直接拿出来就可以穿上出门,女生就不需要太关心这个套装是如何搭配的(很有审美观男朋友已经帮忙搭配好了,女生也比较满意),是不是方便了许多了呢?
1、简单工厂模式(Simple Factory
)
- 工厂是一个简单的类,不是抽象类或者是接口,其中生成返回具体产品通常使用
if-else
或者swith-case
。 - 返回产品的方法一般都是
static
,所有也称之为静态工厂方法模式(Static FactoryMethod Pattern
)。 - 也可以认为:简单工厂模式看为工厂方法模式的一种特例,所以优缺点等介绍将不做,具体请看工厂方法模式。
2、工厂方法模式(Factory Method
)
特点
(1)生成返回具体产品是通过实现抽象工厂类或者工厂接口方式。
(2) 一组产品依赖实现一个抽象类或接口。
(3)一个工厂工具(工厂实现类)返回产品组中一个具体产品类。
UML图
ConcreteProductA
只依赖ConcreteFactroyA
,ConcreteFactroyA
只返回ConcreteProductA
。- 一组产品
ConcreteProductA
与ConcreteProductB
只实现Product
产品接口; - 一个工厂接口
AbstracFactory
也只依赖一个产品接口Product
。
代码实现:
AbstractFactory.java:
/**
* 抽象工厂类:返回具体产品
* @author Lijian
*
*/
interface AbstractFactory {
Product createProduct();
}
Product.java:
/**
* 抽象产品类:定义产品
* @author Lijian
*
*/
interface Product {
void method1();
void method2();
}
ConcreteProductA.java:
/**
* 产品类
* @author Lijian
*
*/
public class ConcreteProductA implements Product{
@Override
public void method1() {
System.out.println("ConcreteProductA implement method1()");
}
@Override
public void method2() {
System.out.println("ConcreteProductA implement method2()");
}
}
ConcreteProductB.java
/**
* 产品类
* @author Lijian
*
*/
public class ConcreteProductB implements Product{
@Override
public void method1() {
System.out.println("ConcreteProductB implement method1()");
}
@Override
public void method2() {
System.out.println("ConcreteProductB implement method2()");
}
}
ConcreteFactoryA.java
/**
* 工厂工具类A
* @author Lijian
*
*/
public class ConcreteFactoryA implements AbstractFactory{
//构造器,可以外部调用对外创建实例
public ConcreteFactoryA() {}
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
ConcreteFactoryB.java:
/**
* 工厂工具类B
* @author Lijian
*
*/
public class ConcreteFactoryB implements AbstractFactory{
//构造器,可以外部调用对外创建实例
public ConcreteFactoryB() {}
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
Consumer.java
/**
* 客户端消费者类
* @author Lijian
*
*/
public class Consumer {
public static void serviceFactory(AbstractFactory factory) {
Product product = factory.createProduct();//upcast向上转型
System.out.println(factory.getClass().getSimpleName()+" create "+product.getClass().getSimpleName()+":");
product.method1();
product.method2();
}
public static void main(String[] args) {
//传入工厂工具类ConcreteFactoryA/B
serviceFactory(new ConcreteFactoryA());
serviceFactory(new ConcreteFactoryB());
}
}
结果如下:
ConcreteFactoryA create ConcreteProductA:
ConcreteProductA implement method1()
ConcreteProductA implement method2()
ConcreteFactoryB create ConcreteProductB:
ConcreteProductB implement method1()
ConcreteProductB implement method2()
3、抽象工厂模式(Abstract Factory
)
首先应该先知道产品族与等级结构指的是什么:
等级结构:工厂模式提供的一系列产品,即全部依赖实现于同一个接口或者抽象类产品。
产品族:指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族。
特点
(1)提供创建一组相关相互依赖对象的接口,而无需指定他们具体的类。
(2)工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。
(3)抽象工厂实现类提供的产品可以为多个,这多个产品可以实现依赖于不同的产品接口或抽象类产品。
UML图
ConcreteProductA
只依赖ConcreteFactroyA
,ConcreteFactroyA
只返回ConcreteProductA
。- 一组产品
ConcreteProductA
与ConcreteProductB
只实现Product
产品接口; - 一个工厂接口
AbstracFactory
也只依赖一个产品接口Product
。
代码实现
这里只举例实现关键部门,没有完整代码实现:
产品相关类:
//多个抽象接口
interface AbstractProductA {
public void show();
}
interface AbstractProductB {
public void show();
}
class ProductA implements AbstractProductA {
public void show() {
System.out.println("ProductA implement AbstractProductA");
}
}
class ProductB implements AbstractProductB {
public void show() {
System.out.println("ProductB implement AbstractProductB");
}
}
工厂相关类:
//一个工厂接口返回多个产品
interface AbstractFactory{
public AbstractProductA createProductA();
public AbstractProductB createProductB();
}
//这些产品之间互相有关联,一个工厂工具返回多个产品
class ConcreteFactory implements AbstractFactory{
public AbstractProductA createProductA() {
return new ProductA();
}
public AbstractProductB createProductB() {
return new ProductB();
}
}
4、工厂方法与抽象工厂比较
(1)工厂方法模式:
- 定义一个用于创建对象的接口,让子类(
ConcreteFactoryA/B
)决定实例化哪一个类,遵循了开放—封闭原则。 - 相对比之下,工厂方法模式的扩展性比较好,比如我们需要增加一个产品,则需要增加两个工厂相关类与一个产品实现类,但是不需要关心与其他产品之间的复杂关系。
- 产品只依赖产品接口,与消费者无关,实现了一定的解耦。
- 抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,不能做到产品的相互交流。
(2)抽象工厂:
抽象工厂模式是工厂方法模式的升级版,除了具备工厂方法模式的优点之外,还具备以下几点:
- 由于是针对产品族的,所以每个产品的相互约束,相互关联都可以在内部实现,而不需要对外重新创建管理产品的相关类(具体情况根据业务情况而定)
- 面对复杂的产品生产环境,抽象工厂模式可以应对。
- 扩展性差,面对增加需求变动时,需要在已经确定了产品集合中增加产品扩展工厂接口,之后还需要确定产品之间的关联依赖。