跟JBPM学设计模式之工厂方法模式

JBPM学设计模式之工厂方法模式

 

模式简介

         工厂方法模式,定义一个用于创建对象的接口,让子类决定实例化那个类,其使一个类的实例化延迟到其子类中。

         前边我们学习了简单工厂模式,简单工厂模式的最大优势在于工厂类中包含了必要逻辑判断,根据客户端的条件动态实例化相关的类,对于客户端不需要了解具体的产品类,所以解除了对具体产品类的依赖。在引入新的产品的时候,我们不需要修改客户端代码,但是必须修改工厂,所以违背了开闭原则。

         工厂方法模式是简单工厂模式的进一步抽象和推广。由于工厂类使用多态性,使其即保持了简单工厂模式的优点,也克服了其缺点。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体的创建工作交给子类去做,它仅仅负责给出具体工厂类需要实现的接口。通过这种抽象和依赖倒转的结果,这样就可以允许我们在不修改具体工厂类的前提下,引进新的产品类型。

         工厂方法模式的结构如下图,其一般会涉及到一下角色

 

1. 工厂方法模式结构图

 

         抽象工厂:为具体的工厂类提供必需实现的接口,其通常是与具体的业务应用无关。

         具体工厂:其实现抽象工厂定义的接口,其接受客户的调用创建产品对象。

         抽象产品:工厂方法模式创建的产品对象的父类,其提供具体产品需要继承的成员。

         具体产品:工厂类需要创建的产品对象。

JBPM中的工厂方法模式

         日志功能往往是每个软件系统必备的模块,JBPM也不例外,其本身支持两种日志类型,我们可以通过配置灵活的选择。其中对Log对象的实例化使用了工厂方法模式,具体的结构图如下

 

 

1. JBPM中的工厂方法模式结构图

 

         Log类作为产品基类,其提供了具体的产品需要实现的所有的接口,在这里就是获取日志等级开关和相应等级记录日志的接口;但是在这里其提供了一个静态的getLog方法,它是做什么用的呢?从代码的实现上来看,其持有一个工厂实例,如果这个工厂实例已经被实例化,那就直接调用工厂创建具体的日志类;如果还没有实例化,就读取相关的配置文件,根据配置来实例化相应的工厂类,然后调用工厂类创建产品。我们可以看到这一小段代码中使用了单例模式和简单工厂模式;单例模式避免每次获取Log对象的时候读取、解析配置文件、初始化相关的工厂类等繁琐的工作;简单工厂模式封装了具体工厂类的实例化,间接的负责具体产品的创建,这样客户就不需要依赖具体的工厂类,直接调用getLog就可以了。具体代码如下

         View Code

 
public  abstract  class Log {
  
   static LogFactory logFactory;

   // 使用简单工厂模式,根据配置初始化具体的工厂
   public  static  synchronized Log getLog(String name) {
     if (logFactory== null) {
      
      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

       //  if logging.properties is available on the classpath
       if (classLoader.getResource("logging.properties")!= null) {
        logFactory =  new Jdk14LogFactory();
        
       //  if log4j is available on the classpath
      }  else  if (isLog4jAvailable(classLoader)) {
        logFactory =  new Log4jLogFactory();
        
      }  else {
        logFactory =  new Jdk14LogFactory();
         
      }
    }
     return logFactory.getLog(name);
  }

   static  boolean isLog4jAvailable(ClassLoader classLoader) {
     try {
      Class.forName("org.apache.log4j.LogManager",  false, classLoader);
       return  true;
    }  catch (ClassNotFoundException e) {
       return  false;
    }
  }

   // 声明具体的log类需要实现的接口
   public  abstract  void error(String msg);
   public  abstract  void error(String msg, Throwable exception);

   public  abstract  boolean isInfoEnabled();
   public  abstract  void info(String msg);
   public  abstract  void info(String msg, Throwable exception);

   public  abstract  boolean isDebugEnabled();
   public  abstract  void debug(String msg);
   public  abstract  void debug(String msg, Throwable exception);

   public  abstract  boolean isTraceEnabled();
   public  abstract  void trace(String msg);
   public  abstract  void trace(String msg, Throwable exception);
  
   public  abstract  boolean isWarnEnabled();
   public  abstract  void warn(String msg);
   public  abstract  void warn(String msg, Throwable exception);
  

         Log4jLog实现了Log定义的一些结构,并将相应的接口需要完成的工作委托给org.apache.log4j.Logger来实现,具体代码如下

         View Code

 
public  class Log4jLog  extends Log {

  org.apache.log4j.Logger log;
  
   public Log4jLog(org.apache.log4j.Logger log) {
     this.log = log;
  }

   public  void error(String msg) {
    log.error(msg);
  }

   public  void error(String msg, Throwable exception) {
    log.error(msg, exception);
  }

   public  boolean isInfoEnabled() {
     return log.isInfoEnabled();
  }

   public  void info(String msg) {
    log.info(msg);
  }

   public  void info(String msg, Throwable exception) {
    log.info(msg, exception);
  }

   public  boolean isDebugEnabled() {
     return log.isDebugEnabled();
  }

   public  void debug(String msg) {
    log.debug(msg);
  }

   public  void debug(String msg, Throwable exception) {
    log.debug(msg, exception);
  }

   public  boolean isTraceEnabled() {
     return log.isTraceEnabled();
  }

   public  void trace(String msg) {
    log.trace(msg);
  }

   public  void trace(String msg, Throwable exception) {
    log.trace(msg, exception);
  }
  
   public  boolean isWarnEnabled() {
     return log.isEnabledFor(Level.WARN);
  }
  
   public  void warn(String msg) {
    log.warn(msg);
  }
  
   public  void warn(String msg, Throwable exception) {
    log.warn(msg, exception);
  }
  

         同样的Jdk14Log作为具体的产品类,其也将相应的工作委托给java jdk提供的日志类来实现产品基类Log的接口,具体代码如下

         View Code

 
public  class Jdk14Log  extends Log {
  
  Logger log;

   public Jdk14Log(Logger logger) {
     this.log = logger;
  }

   public  void error(String msg) {
    log.log(Level.SEVERE, msg);
  }

   public  void error(String msg, Throwable exception) {
    log.log(Level.SEVERE, msg, exception);
  }

   public  boolean isInfoEnabled() {
     return log.isLoggable(Level.INFO);
  }

   public  void info(String msg) {
    log.log(Level.INFO, msg);
  }

   public  void info(String msg, Throwable exception) {
    log.log(Level.INFO, msg, exception);
  }

   public  boolean isDebugEnabled() {
     return log.isLoggable(Level.FINE);
  }

   public  void debug(String msg) {
    log.log(Level.FINE, msg);
  }

   public  void debug(String msg, Throwable exception) {
    log.log(Level.FINE, msg, exception);
  }

   public  boolean isTraceEnabled() {
     return log.isLoggable(Level.FINEST);
  }

   public  void trace(String msg) {
    log.log(Level.FINEST, msg);
  }

   public  void trace(String msg, Throwable exception) {
    log.log(Level.FINEST, msg, exception);
  }
  
   public  boolean isWarnEnabled() {
     return log.isLoggable(Level.WARNING);
  }
  
   public  void warn(String msg) {
    log.warning(msg);
  }
  
   public  void warn(String msg, Throwable exception) {
    log.log(Level.WARNING, msg, exception);
  }
  

         LogFactory作为工厂的基类,其提供了具体工厂类需要实现的创建接口getLog,代码如下

         View Code

 
public  interface LogFactory {

  Log getLog(String name);

         Log4jLogFactory实现工厂接口的方法,负责实例化Log4jLog代码如下

         View Code

 
public  class Log4jLogFactory  implements LogFactory {

   public Log getLog(String name) {
     return  new Log4jLog(LogManager.getLogger(name));
  }

         Jdk14LogFactory也实现工厂接口的方法,负责实例化Jdk14Log

 View Code

 
public  class Jdk14LogFactory  implements LogFactory {

   public Log getLog(String name) {
     return  new Jdk14Log(Logger.getLogger(name));
  }  

工厂方法模式的优劣

         工厂方法模式抽象出工厂基类,使其只提供创建产品的接口,将创建具体产品的职责下放到工厂子类中,同时每个工厂子类只负责创建一种产品,解除了简单工厂类对所有产品的依赖,所以当我们新增产品的时候,只要同时新增相应的工厂类就可以了。但是如果仔细观察我们就会发现,使用工厂方法模式时,客户端需要决定实例化哪个工厂来创建产品,这个选择判断的问题还是存在的,其实,工厂方法把简单工厂的内部判断逻辑转移到了客户端代码来进行,在添加新的产品时,本来是修改工厂类,而现在是修改客户端。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值