设计模式-工厂方法模式

工厂方法模式(Factory Method Pattern),也被叫做工厂模式,虚拟构造器模式或多态工厂模式,属于类创建模式。在工厂方法模式中,父类定义了创建产品的公共接口, 具体的构造过程由子类完成,当有一个新的产品需要构建时,不需要去修改父类,仅仅增加一个子工厂类,即可完成,更加符合开闭原则。

设计模式-概述

结构

包含如下角色:

  1. Product 抽象产品
  2. ConcreteProduct 具体产品
  3. Factory 抽象工厂
  4. ConcreteFactory 具体工厂

factory-method-1.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@startuml factory-method-1
!include ./common.iuml

Class(Product,"抽象产品") << abstract >> {
+use() : void
}

Class(ConcreteProduct,"具体产品") {
+use() : void
}

Class(Factory,"抽象工厂") << abstract >> {
+factoryMethod() : Product
}

Class(ConcreteFactory,"具体工厂") {
+factoryMethod() : Product
}


note as N1
return new ConcreteProduct();
end note

Product <|-- ConcreteProduct
ConcreteProduct <-left- ConcreteFactory
Factory <|-- ConcreteFactory
ConcreteFactory -right- N1

@enduml

使用时序

factory-method-2.png

1
2
3
4
5
6
7
8
9
10
11
12
13
@startuml factory-method-2

actor iMain
participant ConcreteFactory
participant ConcreteProduct

activate iMain
iMain -> ConcreteFactory : 1.0 factoryMethod():Product
activate ConcreteFactory
ConcreteFactory --> ConcreteProduct : 1.1 <<create>>
iMain -> ConcreteProduct : 1.2 use()

@enduml

代码实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* CreateUser: canyuda
* CreateTime: 2019/9/29 21:26
* Description:
*/
public class Main {
public static void main(String[] args) {
Factory factory = new ConcreteFactory();
Product product = factory.factoryMethod();
product.use();
}
}

abstract class Product {
abstract public void use();
}

abstract class Factory {
abstract Product factoryMethod();
}


class ConcreteProduct extends Product {

@Override
public void use() {
System.out.println("use ConcreteProduct");
}
}

class ConcreteFactory extends Factory {

@Override
Product factoryMethod() {
return new ConcreteProduct();
}
}

使用场景

是简单工厂模式的增强版本,既保持了简单工厂的优点,又克服了简单工厂类的缺点, 可以在不修改工厂类的情况下,产生新的Product, 仅需要继承抽象工厂类就好了。

  • 一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
  • 一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
  • 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

应用

MyBatis中的SqlSessionFactory, 默认提供了两个实现类 org.apache.ibatis.session.SqlSessionManagerorg.apache.ibatis.session.defaults.DefaultSqlSessionFactory