1、简单工厂模式:
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类,简单工厂是“固定的”,因为只有一个实现,没有子类。它不属于23种设计模式之一,但在实际应用中却比较常见,当使用构造器构造时太复杂时可以用这种方式。先看个简单例子:
public class FruitFactory {
public static Fruit get(String fruitType) {
if ("apple".equals(friutType)) {
return new Apple();
} else if ("orange".equals(friutType)) {
return new Orange();
}
}
}
FruitFactory.get("apple")
简单工厂有静态工厂和实例工厂,上面属于静态工厂,下面看下实例工厂:
public class FruitFactory {
public Fruit get(String fruitType) {
if ("apple".equals(friutType)) {
return new Apple();
} else if ("orange".equals(friutType)) {
return new Orange();
}
}
}
FruitFactory fruitFactory = new FruitFactory();
fruitFactory.get("")
静态工厂利用静态方法定义一个简单的工厂,相较而言,静态工厂不需要使用创建对象的方法来实例化对象,但不能通过继承改变创建对象的行为。
以上两种简单工厂在Spring中都有其配置方式,静态工厂xml配置如下:
<bean id=“apple" class="...FruitFactory" factory-method="get">
<constructor-arg>
<value>apple</value>
</constructor-arg>
</bean>
非静态工厂xml配置如下:
<bean id=“fruitFactory" class="...FruitFactory”/>
<bean id=“apple”factory-bean="...fruitFactory" factory-method="get">
<constructor-arg>
<value>apple</value>
</constructor-arg>
</bean>
个人认为以上xml配置方式,包括后面的FactoryBean接口实现类的配置,都可以用spring后面出的@Bean代替。不需要factory-method,factory-bean这类标签。
Spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。BeanFactory接口是含有许多bean定义的对象实现的,每个bean都由一个字符串名称作为惟一标识。根据bean定义,工厂将返回对象的独立实例(prototype模式),或者单个共享实例(替代singleton模式,其实例是工厂范围内的单例)。API是相同的,返回哪种类型的实例取决于bean工厂配置。从Spring 2.0开始,可以根据具体的应用程序上下文使用更多的scope(如web环境的request和session scope)
2、工厂方法模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。其使用场景通常是类中有一些通用的处理流程,但希望更改实际使用的具体对象类型。
public abstract class FruitProducer {
protected abstract Fruit makeFruit();
public void produceFruit() {
private final Fruit f = makeFruit(); // The fruit we will work on..
//省略代码,创建fruit后执行的公共功能
}
}
然后,通过在子类中实现工厂方法,可以重用FruitProducer.produceFruit()中的公共功能:
class OrangeProducer extends FruitProducer {
@Override
protected Fruit makeFruit() {
return new Orange();
}
}
原来简单工厂是一个对象负责所有具体类的实例化,而工厂方法模式是定义一个用于创建对象的接口,由一群子类负责实例化,简单工厂不具备工厂方法的弹性。
Spring中的FactoryBean就是典型的工厂方法模式。如下图:
FactoryBean接口由BeanFactory中配置的对象实现,这些对象本身就是用于创建对象的工厂。如果一个bean实现了这个接口,那么它就是创建对象的工厂bean,即FactoryBean,而不是bean实例本身。我们常用的ProxyFactoryBean就是基于FactoryBean实现的。FactoryBean接口如下,其实现类源码大家可以自己查阅。
public interface FactoryBean <T> {
T getObject() throws java.lang.Exception;
java.lang.Class<?> getObjectType();
boolean isSingleton();
}
工厂模式体现了一个非常重要的设计原则,即依赖倒置原则,参照前面的例子,假如在FruitProducer的makeFruit方法内部直接通过new Apple(),new Orange()方式创建水果对象的,而不委托给工厂,那就意味着FruitProducer作为一个高层的组件,直接依赖的低层的组件,依赖于具体的水果对象,这些实现类改变了,FruitProducer也要同步改变,而且每增加一个水果类型,FruitProducer就要增加一个依赖。
低层模块的修改会直接影响到高层模块,这样高层模块很难在不同的环境里复用,因此高层模块不能依赖于低层模块,不管是高层还是低层模块,都要依赖于抽象,即上面代码中的Fruit抽象类,通过这样的“依赖倒置”,减少了高层模块对低层模块的依赖,提高了高层模块的可复用性。工厂模式正是实现这一原则的重要武器。
java达人
ID:drjava
(长按或扫码识别)