[知识点] 漫谈设计模式 04
?
××××× Factory Method ×××××
# 4.1 概述
- 如何使用工厂方法模式,创建普通的类。
- 场景
- 只关心该接口提供的功能
- 创建过程复杂。 如需要初始化其他关联的资源类,读取配置文件等等
- 接口有很多具体实现或者抽象类有很多子类时,你可能需要为客户代码写一大串if-else逻辑来决定使用
哪个具体实现或者子类。【不理解为什么要写一大串if-else】
- 隐藏类的内部结构降低耦合读
- 优化性能,例如缓存大对象或者初始化比较耗时的对象【实例?】
# 4.2 工厂方法模式
- Define an interface for creating an object, but let subclass to decide which class to instantiate.
Factory Method lets a class defer instantiation to subclass.
4.2.1 类图
interface Product <-- ConcreteProduct
interface Factory <-- ConcreteFactory
4.2.2 代码 (略)
[code]
public class Client {
private Factory factory;
public Client (Factory factory) {
this.factory = factory;
}
public void doSomething() {
Product product = factory.createProduct();//不知product是如何初始化的【封装,起到解耦作用】
//do something.
}
public static void main(String args[]) {
Client client = new Client( new ConcreteFactory());
client.doSomething();
}
}
[code]
- 如果产品很多(实现类很多),可以定义一个参数化的工厂方法。
[code]
public Production createProduction(String type) {
if ("type1".equals(type)) {
return new AProduction();
} else if ("type2".equals(type)) {
return new BProduction();
} else {
return other instance.
}
}
[code]
4.2.3 创建数据库连接对象
- 实例化对象非常耗资源,选择缓存这些实例对象。于是,工厂对象里面创建一个【缓存池】缓存这些实例对象。
- 在Java Web应用中,ThreadLocal 缓存数据连接对象。
- 软引用和弱引用非常适合做缓存。 java.lang.ref
- [Java 强引用、 软引用、 弱引用、虚引用]
- 在J2EE Web应用中,每接收到一个http请求,就会启动一个线程来处理这个请求,使用ThreadLocal类这样很容易实现
在处理同一个请求的整个过程中,尽可能使用同一个数据库连接对象,使用完成后,JVM总会自动处理该数据库连接对象。
[code]
import java.sql.Connection;
public class ConnectionFactory {
private static final ThreadLocal<Connection> connections = new ThreadLocal<Connection>();
//other variables and methods?
public Connection currentConnection() {
Connection conn = connections.get();
if (conn == null) {
conn = createConnection();
connections.set(conn);
}
return conn;
}
[code]
# 4.3 静态工厂方法
4.3.1 概述
- 为每一个类创建一个工厂方法方法类会引起工厂类泛滥。
- 静态的工厂方法:在每个类里面实现一个静态的工厂方法,就不需要额外的工厂类了。
- e.g
public static Integer valueOf (int i) {
if (i > -128 && i <= IntegerCache.high) {
return IntegerCache.cache[i+128];
} else {
return new Integer(i);
}
}
4.3.2 优缺点
- 【优】封装复杂的初始化过程,实现实例的缓存
- 1. 一般构造函数是private,导致此类不能被子类实例化
- 2. 静态方法没有面向对象的特征,不能被override
?