1、工厂方法
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。
工厂方法的目的是使得创建对象和使用对象是分离的,并且客户端总是引用抽象工厂和抽象产品:
┌─────────────┐ ┌─────────────┐
│ Product │ │ Factory │
└─────────────┘ └─────────────┘
▲ ▲
│ │
┌─────────────┐ ┌─────────────┐
│ ProductImpl │<─ ─ ─│ FactoryImpl │
└─────────────┘ └─────────────┘
工厂接口:
public interface NumberFactory {
Number parse(String s);
}
工厂实现类:
public class NumberFactoryImpl implements NumberFactory {
public Number parse(String s) {
return new BigDecimal(s);
}
}
产品接口是Number
,NumberFactoryImpl
返回的实际产品是BigDecimal
客户端如何创建NumberFactoryImpl
呢?通常我们会在接口Factory
中定义一个静态方法getFactory()
来返回真正的子类:
public interface NumberFactory {
// 创建方法:
Number parse(String s);
// 获取工厂实例:
static NumberFactory getFactory() {
return impl;
}
//获取实现类
static NumberFactory impl = new NumberFactoryImpl();
}
在客户端中,我们只需要和工厂接口NumberFactory
以及抽象产品Number
打交道:
NumberFactory factory = NumberFactory.getFactory();
Number result = factory.parse("123.456");
调用方可以完全忽略真正的工厂NumberFactoryImpl
和实际的产品BigDecimal
,这样做的好处是允许创建产品的代码独立地变换,而不会影响到调用方。
2、静态工厂方法(Static Factory Method)。
静态工厂方法广泛地应用在Java标准库中
Integer n = Integer.valueOf(100);
#Integer n = new Integer(100);
Integer
既是产品又是静态工厂。它提供了静态方法valueOf()
来创建Integer
。那么这种方式和直接写new Integer(100)
有何区别呢?我们观察valueOf()
方法:
public final class Integer {
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
...
}
valueOf()
内部可能会使用new
创建一个新的Integer
实例,但也可能直接返回一个缓存的Integer
实例。对于调用方来说,没必要知道Integer
创建的细节。
如果调用方直接使用Integer n = new Integer(100)
,那么就失去了使用缓存优化的可能性。
工厂方法可以隐藏创建产品的细节,且不一定每次都会真正创建产品,完全可以返回缓存的产品,从而提升速度并减少内存消耗。
3、抽象工厂方法
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
抽象工厂模式和工厂方法不太一样,它要解决的问题比较复杂,不但工厂是抽象的,产品是抽象的,而且有多个产品需要创建,因此,这个抽象工厂会对应到多个实际工厂,每个实际工厂负责创建多个实际产品:
┌────────┐
─ >│ProductA│
┌────────┐ ┌─────────┐ │ └────────┘
│ Client │─ ─>│ Factory │─ ─
└────────┘ └─────────┘ │ ┌────────┐
▲ ─ >│ProductB│
┌───────┴───────┐ └────────┘
│ │
┌─────────┐ ┌─────────┐
│Factory1 │ │Factory2 │
└─────────┘ └─────────┘
│ ┌─────────┐ │ ┌─────────┐
─ >│ProductA1│ ─ >│ProductA2│
│ └─────────┘ │ └─────────┘
┌─────────┐ ┌─────────┐
└ ─>│ProductB1│ └ ─>│ProductB2│
└─────────┘ └─────────┘