设计模式-工厂模式(结合spring源码)

116 阅读1分钟

工厂模式的分类

在使用工厂之前,先来简单了解一下什么是工厂模式。
  • 简单工厂

    • 第一种实现方法,每次调用都会产生一个新的对象
    /**
    * 创建配置类
    */
    public class ConfigFactory {
    
     public static Config createConfig(){
        return new Config();
     }
    }
    
    
    • 第二种实现方法,缓存对象,调用的时候直接返回
    /**
     * 创建配置类
     */
    public class ConfigFactory {
      private static final Map<String, Config> cachedParsers = new HashMap<>();
    
      public static final String CACHE_KEY = "CACHE";
      static {
     	  // 根据自己的逻辑初始化
          cachedParsers.put(CACHE_KEY,new Config());
      }
    
      public static Config createConfig(){
          return cachedParsers.get(CACHE_KEY);
      }
    }
    
  • 工厂方法

工厂方法能够比较简洁的去除掉代码中复杂的if分支逻辑。
//典型实现
public abstract class Factory {
    public abstract Config createConfig();
}

public class ConfigFactory implements Factory {
    @Override
    public  Config createConfig(){
        return new Config();
    }
}
这样当我们新增一种 parser 的时候,只需要新增一个实现了 ConfigFactory 接口的 Factory 类即可。

tip: 这种实现方式,目前还没有解决问题,因为仍然需要不同if分支来新建对应的工厂,如ConfigFactory。想要比较好的解决问题,还需要引入另外一个工厂,即工厂的工厂。

public class FactoryFactory{
    public static final Map<String, Factory> cachedFactories = new HashMap<>();
    public static final String CACHE_KEY = "CONFIG";

    static {
        cachedFactories.put(CACHE_KEY,new ConfigFactory());
    }

    /**
     * 根据逻辑来创建工厂
     * @return
     */
    public static Factory createFactroy(String type){
        if(StringUtils.isBlank(type)){
            //throw new NullPointerException();
            return null;
        }
        return cachedFactories.get(type);
    }
}
  • 抽象工厂 抽象工厂可以使用的情景比较少,主要用于一些对于待生产对象特别复杂的工厂。让一个工厂复杂创建不同类型的对象。
public abstract class Factory {
    
    public abstract Config createFileConfig();
    
    public abstract Config createClassConfig();
}

public class ConfigFactory implements Factory {
    @Override
    public  Config createFileConfig(){
        return new FileConfig();
    }
    public  Config createClassConfig(){
        return new ClassConfig();
    }
}
一般情况下使用不到!~

工厂模式的使用

前面介绍了三种工厂模式的实现,下面就就可以来看看我们该在什么情况下来进行使用。

  1. 代码中存在大段的 if-else 分支判断,动态地根据不同的类型创建不同的对象。可以考虑使用工厂模式。将if-else创建对象的代码抽离出来,放到工厂类中。
  2. 单个对象本身的创建过程比较复杂,比如前面提到的要组合其他类对象,做各种初始化操作,将对象的创建过程封装到工厂类中。

Spring中的工厂模式

  1. 工厂(最小原型设计)
public interface ApplicationContext extends ... {
	AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
}
// 工厂方法--不同的实现
public abstract class AbstractApplicationContext extends ... {
    public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
		return getBeanFactory();
	}
    
    @Override
	public final ConfigurableListableBeanFactory getBeanFactory() {
		synchronized (this.beanFactoryMonitor) {
			if (this.beanFactory == null) {
				throw new IllegalStateException("BeanFactory not initialized or already closed - " +
						"call 'refresh' before accessing beans via the ApplicationContext");
			}
			return this.beanFactory;
		}
	}
}

public class GenericApplicationContext extends ...{

	@Override
	public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
    		//Assert that this context's BeanFactory is currently active
		assertBeanFactoryActive();
		return this.beanFactory;
	}
}

  1. 工厂的工厂,DefaultSingletonBeanRegistry
public class DefaultSingletonBeanRegistry extends... {
    	// 初始化容器
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** Set of registered singletons, containing the bean names in registration order. */
	private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

	/** Map between containing bean names: bean name to Set of bean names that the bean contains. */
	private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);

	/** Map between dependent bean names: bean name to Set of dependent bean names. */
	private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

	/** Map between depending bean names: bean name to Set of bean names for the bean's dependencies. */
	private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

	@Override
	public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
    		//注册bean
		Assert.notNull(beanName, "Bean name must not be null");
		Assert.notNull(singletonObject, "Singleton object must not be null");
		synchronized (this.singletonObjects) {
			Object oldObject = this.singletonObjects.get(beanName);
			if (oldObject != null) {
				...
			}
			addSingleton(beanName, singletonObject);
		}
	}
    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
            
            // 获取Bean对象,如果没有的话就创建
            ...
             
            }


}
这里我们为了跟设计模式对应的更加清晰,将部分源码忽略,这样可以更加清晰。