工厂方法模式是使用频率非常高的设计模式,在日常开发经常可以见到。
工厂方法模式的定义:
Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.(定义一个用于创建对象的 接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。) |
---|
工厂方法模式的通用类图如图8-1所示:
图8-1:工厂方法模式通用类图
在工厂方法模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象的定 义;Creator为抽象创建类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂 ConcreteCreator完成的。
工厂方法模式的扩展比较多,以下是比较通用的工厂方法模式实例:
public abstract class Product {
// 产品类的公共方法
public void method1() {
// 业务逻辑处理
}
// 抽象方法
public abstract void method2();
}
public class ConcreteProduct1 extends Product{
@Override
public void method2() {
// TODO Auto-generated method stub
}
}
public class ConcreteProduct2 extends Product{
@Override
public void method2() {
// TODO Auto-generated method stub
}
}
public abstract class Creator {
/** 创建一个产品对象,其输入参数类型可以自行设置 * 通常为String、Enum、Class等,当然也可以为空 */
public abstract <T extends Product> T createProduct(Class<T> c);
}
public class ConcreteCreator {
public <T extends Product> T createProduct(Class<T> c) {
Product product = null;
try {
product = (Product) Class.forName(c.getName()).newInstance();
} catch (Exception e) {
// 异常处理
}
return (T) product;
}
}
public class Client {
public static void main(String[] args) {
Creator creator = new ConcreteCreator();
Product product = creator.createProduct(ConcreteProduct1.class);
/** 继续业务处理 */ }
}
使用工厂方法模式有以下优点:
简单工厂模式并不是一个标准的设计模式,但是在实际开发中是非常有用的。
简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的 实例,被创建的实例通常都具有共同的父类。
以女娲造人为例:女娲在不同的场景下分别造出了白种人、黑种人、黄种人。 类图如下:
图8-2:简单工厂模式类图
public class HumanFactory {
public static <T extends Human> T createHuman(Class<T> c) {
// 定义一个生产出的人种
Human human = null;
try {
// 产生一个人种
human = (Human) Class.forName(c.getName()).newInstance();
} catch (Exception e) {
System.out.println("人种生成错误!");
}
return (T) human;
}
}
public interface Human {
//每个人种的皮肤都有相应的颜色
public void getColor();
//人类会说话
public void talk();
}
public class BlackHuman implements Human{
@Override
public void getColor() {
System.out.println("黑色人种的皮肤颜色是黑色的!");
}
@Override
public void talk() {
System.out.println("Hey!Man.");
}
}
public class WhiteHuman implements Human{
@Override
public void getColor() {
System.out.println("白肤色");
}
@Override
public void talk() {
System.out.println("Calm down!Guy!");
}
}
public class YellowHuman implements Human{
@Override
public void getColor() {
System.out.println("黄土地的颜色!");
}
@Override
public void talk() {
System.out.println("五湖四海皆兄弟!");
}
}
public class NvWa {
public static void main(String[] args) {
// 女娲第一次造人,火候不足,于是白色人种产生了
System.out.println("--造出的第一批人是白色人种--");
Human whiteHuman = HumanFactory.createHuman(WhiteHuman.class);
whiteHuman.getColor();
whiteHuman.talk();
// 女娲第二次造人,火候过足,于是黑色人种产生了
System.out.println("\n--造出的第二批人是黑色人种--");
Human blackHuman = HumanFactory.createHuman(BlackHuman.class);
blackHuman.getColor();
blackHuman.talk(); // 第三次造人,火候刚刚好,于是黄色人种产生了
System.out.println("\n--造出的第三批人是黄色人种--");
Human yellowHuman = HumanFactory.createHuman(YellowHuman.class);
yellowHuman.getColor();
yellowHuman.talk();
}
}
Spring框架对工厂方法模式的应用是非常经典的。
首先看一下什么是IOC和DI:
带着问题将这两个概念拆解开来:
IOC/DI对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IOC/DI思想中,应用程序就变成被动的了,被动的等待IOC/DI容器来创建并注入它所需要的资源了。 这么小小的一个改变其实是编程思想的一个大进步,这样就有效的分离了对象和它所需要的外部资源,使得它们松散耦合,有利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
SpringBean 的创建是典型的工厂模式,IOC容器实现,就是利用一系列的 Bean 工厂,在 Spring 中有许多的 IOC 容器的实现供用户选择和使用,其相互关系如下:
图8-3:Spring IOC容器相互关系
其中 BeanFactory 作为最顶层的一个接口类,它定义了 IOC 容器的基本功能规范,BeanFactory 有三个子类: ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory。最终的 默认实现类是 DefaultListableBeanFactory,实现了所有的接口。定义这么多层次的接口是为了适应不同的场景。例如 ListableBeanFactory 接口表示这些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是这些Bean是有继承关系的 , 也就是每个 Bean 有 可 能 有 父 Bean 。 AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则。这四个接口共同定义了 Bean 的集合、Bean 之间的 关系、以及 Bean 行为。
ackage org.springframework.beans.factory;
import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1) throws BeansException;
<T> T getBean(String var1, Class<T> var2) throws BeansException;
Object getBean(String var1, Object... var2) throws BeansException;
<T> T getBean(Class<T> var1) throws BeansException;
<T> T getBean(Class<T> var1, Object... var2) throws BeansException;
<T> ObjectProvider<T> getBeanProvider(Class<T> var1);
<T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
boolean containsBean(String var1);
boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
@Nullable
Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
String[] getAliases(String var1);
}
参考:
【1】:《设计模式之禅》 【2】:《Java设计模式》 【3】:《Design-Pattern包教不包会(设计模式包教不包会)》 【4】:《研磨设计模式》 【5】:详解设计模式之工厂模式(简单工厂+工厂方法+抽象工厂) 【6】:《深度分析Spring源码》