工厂模式:简单工厂&抽象工厂
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,它提供了一种创建对象的方式,使得创建对象的过程与使用对象的过程分离。
工厂模式提供了一种创建对象的方式,而无需指定要创建的具体类。
简单工厂模式
接口及其实体类:
public interface Shape {
void draw();
}
// 实现圆形类
class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
// 实现矩形类
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
// 实现三角形类
class Triangle implements Shape {
@Override
public void draw() {
System.out.println("绘制三角形");
}
}
工厂类:
注:这里利用反射创建对象,采用泛型控制输入参数必须是Shape的实现类
// 形状工厂类
class ShapeFactory {
public <T extends Shape > T getShape(Class<T> c) {
T shape = null;
try {
shape = c.getDeclaredConstructor().newInstance();
} catch (Exception e) {
System.out.println("类加载失败");
}
return shape;
}
}
测试运行:
public class example {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
Circle shape = shapeFactory.getShape(Circle.class);
shape.draw();
Triangle shape1 = shapeFactory.getShape(Triangle.class);
shape1.draw();
Rectangle shape2 = shapeFactory.getShape(Rectangle.class);
shape2.draw();
}
}
结果:
绘制圆形
绘制三角形
绘制矩形
工厂方法模式
工厂方法模式没用改变实体类的代码,而是拓展了工厂类,定义了一个创建对象的工厂接口(或者抽象类),让工厂子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
比如修改工厂类如下:
// 形状工厂类
abstract class ShapeFactory {
public abstract <T extends Shape > T getShape(Class<T> c);
}
class ShapeFactoryImpl extends ShapeFactory {
public <T extends Shape> T getShape(Class<T> c) {
T t = null;
try {
t = c.getDeclaredConstructor().newInstance();
} catch (Exception e) {
System.out.println("类加载失败");
}
return t;
}
}
相较于简单工厂模式,工厂类的拓展相对更加简单。
抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。主要作用是可以提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。
// 家具抽象工厂接口
interface FurnitureFactory {
Furniture createFurniture();
}
// 现代风格家具工厂
class ModernFurnitureFactory implements FurnitureFactory {
@Override
public Furniture createFurniture() {
return new Furniture(new ModernChair(),new ModernTable());
}
}
// 复古风格家具工厂
class VintageFurnitureFactory implements FurnitureFactory {
@Override
public Furniture createFurniture() {
return new Furniture(new VintageChair(),new VintageTable());
}
}
比如对于实体类,假设有两个产品(椅子,桌子),两种风格(现代,复古),两两排列组合总共有4种家具,这里给出了两种家具的工厂,一种生产现代,一种复古。避免使用时候创建家具过于麻烦。
优点:
- 具体产品在应用层的代码隔离,无需关系创建的细节
- 将一个系列的产品统一到一起创建
缺点: - 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难;
spring中的工厂模式
Spring IOC容器使用工厂模式来管理对象的创建和生命周期。容器作为工厂负责实例化Bean并管理它们的生命周期,主要是beanfactory和applicationcontext两个接口,这两个接口就是spring管理bean的两个顶级抽象工厂。
public interface BeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
//...
}
AbstractBeanFactory 是 BeanFactory 的抽象实现类,实现了 getBean方法的核心逻辑。其中包含spring读取BeanDefinition对象,从缓存中找需要的bean,判断是否有依赖bean,最后创建单例bean。(跳转spring的bean生命周期)
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object bean;
// 尝试从缓存中获取单例 Bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// ...
// 创建新的 Bean 实例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// ...
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// ...
}
// ...
return (T) bean;
}