动态实例化一个类以及一个类的子类(C++/JAVA)

       整理一下理解的几种模式的类的实例化:

Singleton:单态,这个类只能被实例化一次

Factory Method:在Factory子类里,进行,product类的子类的实例化(Simple Factory看为Factory Method模式的一种特例)

Abstract Factory:在Factory子类里,进行,多个“product类的子类”的实例化,一个是product1类的子类,一个是product2类的子类......而且这两个子类是存在关系的

       (他们的区别参考:Factory Method模式与Abstract Factory模式区别12)

       Simple Factory动态实例化一个类,Factory Method和Abstract Factory动态实例化一个类的子类,log4**系列代码有这样的例子,也许他们考虑到还要做完全不同类型的工厂类的管理

1.     log4cplus中Simple Factory和Factory Method的实现方式

       product类:

class  Logger----

class Appender----

    class ConsoleAppender : public Appender

    class FileAppender : public Appender

    class RollingFileAppender : publicFileAppender

 

       Factory类:

class  LoggerFactory----

classAppenderFactory : public BaseFactory----

    class ConsoleAppenderFactory : publicAppenderFactory

    class FileAppenderFactory : publicAppenderFactory

    class RollingFileAppenderFactory : publicAppenderFactory  

(

class LayoutFactory: public BaseFactory----

    class SimpleLayoutFactory : publicLayoutFactory

    class TTCCLayoutFactory : publicLayoutFactory

    class PatternLayoutFactory : publicLayoutFactory

)

       (1)Logger是通过Simple Factory来实现的,LoggerFactory工厂就是实例化一个Logger类
       (2)Appender和Layout是通过Factory Method来实现的,这里AppenderFactory和LayoutFactory就是工厂方法的基工厂类(撇开BaseFactory不谈,对工厂方法而言),ConsoleAppenderFactory子工厂类中做的工作就实例化ConsoleAppender类

       (3)Logger是巧妙的通过
typedef std::map<log4cplus::tstring, Logger> LoggerMap;
       来管理logger_name和Logger实例的 
       (4)Appender类和Layout类很巧妙的新建了一个类AppenderFactoryRegistry和LayoutFactoryRegistry来实现的,主要是考虑到和AppenderFactory平行的LayoutFactory还可以扩展其他的工厂类

       AppenderFactoryRegistry和LayoutFactoryRegistry作用也是利用std::map来管理appender_name和Appender实例

       不管是LoggerFactory还是AppenderFactory,都是通过Factory去维护一个对象名称到对象实例的一个映射关系

2.     log4j中采用的JAVA反射机制

       在log4j中上面两种模式JAVA很简单的采用反射机制就可以实现,JAVA反射机制如下:
       在运行时,判断任意一个对象所属的类
       在运行时,调用任意一个对象的方法
       在运行时,判断任意一个类所具有的成员变量和方法
       在运行时,构造任意一个类的对象(Class.forName(), newInstance())       

       instantiateByClassName是在通过反射实例化对象的时候调用,而findAndSubst是在解析配置文件时,判断是否存在指定键值的。 
//
       已经存在category_factory,可以直接用instantiateByClassName
protected void configureCategoryFactory(Properties props) {
String factoryClassName = OptionConverter.findAndSubst(CATEGORY_FACTORY_KEY,
  props);    
if(factoryClassName != null) {
  LogLog.debug("Setting category factory to ["+factoryClassName+"].");
  categoryFactory = (CategoryFactory) 
              OptionConverter.instantiateByClassName(factoryClassName,
CategoryFactory.class, 
categoryFactory);
  PropertySetter.setProperties(categoryFactory, props, FACTORY_PREFIX + ".");
}
}
///
public
static
Object instantiateByClassName(String className, Class superClass,
Object defaultValue) {
if(className != null) {
  try {
Class classObj = Class.forName(className);
if(!superClass.isAssignableFrom(classObj)) {
  LogLog.error("A \""+className+"\" object is not assignable to a \""+
      superClass.getName() + "\" variable.");
  return defaultValue;  
}
return classObj.newInstance();
  }
  catch (Exception e) {
LogLog.error("Could not instantiate class [" + className + "].", e);
  }
}
return defaultValue;    
}
//
       相当于appender_factory的功能
  Appender parseAppender(Properties props, String appenderName) {
    Appender appender = registryGet(appenderName);
    if((appender != null)) {
      LogLog.debug("Appender \"" + appenderName + "\" was already parsed.");
      return appender;
    }
    // Appender was not previously initialized.
    String prefix = APPENDER_PREFIX + appenderName;
    String layoutPrefix = prefix + ".layout";    


    appender = (Appender) OptionConverter.instantiateByKey(props, prefix,
     org.apache.log4j.Appender.class,
     null);
......
Layout layout = (Layout) OptionConverter.instantiateByKey(props, 
 layoutPrefix,
 Layout.class, 
 null);      
///     
public
static
Object instantiateByKey(Properties props, String key, Class superClass,
Object defaultValue) {


// Get the value of the property in string form
String className = findAndSubst(key, props);
if(className == null) {
  LogLog.error("Could not find value for key " + key);
  return defaultValue;
}
// Trim className to avoid trailing spaces that cause problems.
return OptionConverter.instantiateByClassName(className.trim(), superClass,
 defaultValue);
}
//  

       下面google到的两个个例子(12)是一种完全不同的处理方式,也是一个写C++的同学推荐的方法

       简单工厂类维护一个对象名称到对象实例的映射

       工厂方法基类里面有个静态createInstance函数,然后每个子类继承这个createInstance函数,每个子类的createInstance自己实例化自己一个实例,在外面函数调用基类的createInstance,非常简单就实例化一个子类

3.     简单工厂维护name到实例的映射 

{

    // store instances of pools   
    private static Map<String,SockIOPool> pools =   
        new HashMap<String,SockIOPool>();   
  
  
  
    // empty constructor   
    protected SockIOPool() { }   
  
  
    /**    
     * Factory to create/retrieve new pools given a unique poolName.    
     *    
     * @param poolName unique name of the pool   
     * @return instance of SockIOPool   
     */   
    public static synchronized SockIOPool getInstance( String poolName ) {   
        if ( pools.containsKey( poolName ) )   
            return pools.get( poolName );   
  
        SockIOPool pool = new SockIOPool();   
        pools.put( poolName, pool );   
  
        return pool;   
    }   
  
    /**    
     * Single argument version of factory used for back compat.   
     * Simply creates a pool named "default".    
     *    
     * @return instance of SockIOPool   
     */   
    public static SockIOPool getInstance() {   
        return getInstance( "default" );   
    }  
}    
 

4.     工厂方法模式的智能化实现

#include<iostream>

#include <map>

#include<string>

 

class Shape;

 

typedef Shape*(*FactoryFunction)();

 

class ShapeFactory

{

public:

       static void Register(std::string name,FactoryFunction instanceFunction)

              {m_FactoryFunctions[name] =instanceFunction;};

       static Shape * getInstance(std::stringname)

              { if(m_FactoryFunctions.count(name))                     returnm_FactoryFunctions[name]();

               else       return NULL; }

private:

       staticstd::map<std::string,FactoryFunction> m_FactoryFunctions;

};

 

std::map<std::string,FactoryFunction>ShapeFactory::m_FactoryFunctions;

 

class Shape

{

public:

       virtual void  Draw() = 0;

};

 

class Circle :public Shape

{

public:

       void Draw()  { std::cout << "Drawing aCircle......Done" << std::endl; }

       static Shape *createInstance() {returnnew Circle;}

};

 

class Triangle :public Shape

{

public:

       void Draw()  { std::cout << "Drawing aTriagnle......Done" << std::endl; }

       static Shape *createInstance() {returnnew Triangle;}

};

 

int main()

{

      ShapeFactory::Register("circle",   &  Circle::createInstance);

      ShapeFactory::Register("Triangle", &Triangle::createInstance);

 

       Shape * pShape = NULL;

 

       pShape =ShapeFactory::getInstance("circle");

       if (NULL == pShape)

       {

              std::cout << "can'tfind the product in the factory" << std::endl;

              delete pShape;

       }

       else

       {

              pShape->Draw();

              delete pShape;

       }

       return 0;

}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值