1、上下文及问题
有些对象的实例化比较复杂,比如读哪些配置文件,按哪些步骤初始化等等,这种问题,通常使用工厂方法,来对调用者屏蔽对象的创建逻辑。
2、常见场景
(1)需要对对象的实例进行管理的,比如统计/限制实例个数、实例回收等等,可以交由工厂来管理,比如数据库连接池
(2)多线程情况下,通常需要保证对象的不能够发布逃逸,就是在构造器初始化中将未实例化完成的对象发布出去,比如赋值给外部对象,或者在构造器开线程去访问等等,容易出现问题,因而可以用工厂方法,确保对象构造完后再加上某些必要的步骤之后才发布对象。
(3)如果一个类本身希望由子类来实例化,则很明显的要使用工厂方法
(4)数据库连接池、线程池、ThreadLocal
3、解决方式
(1)使用继承的方式解决,类的实例化延迟到具体的子类
4、模式抽象图
5、代码示例
(1)UML类图代码示例
Product及其实现类
/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.* 抽象产品类*/public abstract class Product { //产品类的公共方法 public void method1(){ //业务逻辑处理 } //抽象方法1 public abstract void method2();}public class ConcreteProduct1 extends Product { public void method2() { //业务逻辑处理 }}public class ConcreteProduct2 extends Product { public void method2() { //业务逻辑处理 }}
工厂及其实现类
public abstract class Factory{ /* * 创建一个产品对象,其输入参数类型可以自行设置 * 通常为String、Enum、Class等,当然也可以为空 */ public abstractT createProduct(Class c);}public class ConcreteFactory extends Factory { public T createProduct(Class 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) { Factory factory= new ConcreteFactory(); Product product = factory.createProduct(ConcreteProduct1.class); /* * 继续业务处理 */ }}
(2)外部利用反射产生单例
public class Singleton { //不允许通过new产生一个对象 private Singleton(){ } public void doSomething(){ //业务处理 }}
外部反射产生单例
/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.*/public class SingletonFactory { private static Singleton singleton; static{ try { Class cl= Class.forName(Singleton.class.getName()); //获得无参构造 Constructor constructor=cl.getDeclaredConstructor(); //设置无参构造是可访问的 constructor.setAccessible(true); //产生一个实例对象 singleton = (Singleton)constructor.newInstance(); } catch (Exception e) { //异常处理 } } public static Singleton getSingleton(){ return singleton; }}
客户端调用
public class Client { public static void main(String[] args) { SingletonFactory.getSingleton().doSomething(); }}
(3)缓存示例
/*** @author cbf4Life cbf4life@126.com* I'm glad to share my knowledge with you all.*/public class Factory { private static final MapprMap = new HashMap(); public static synchronized Product createProduct(String type) throws Exception{ Product product =null; //如果Map中已经有这个对象 if(prMap.containsKey(type)){ product = prMap.get(type); }else{ if(type.equals("Product1")){ product = new ConcreteProduct1(); }else{ product = new ConcreteProduct2(); } //同时把对象放到缓存容器中 prMap.put(type,product); } return product; }}