整理一下理解的几种模式的类的实例化:
Singleton:单态,这个类只能被实例化一次
Factory Method:在Factory子类里,进行,product类的子类的实例化(Simple Factory看为Factory Method模式的一种特例)
Abstract Factory:在Factory子类里,进行,多个“product类的子类”的实例化,一个是product1类的子类,一个是product2类的子类......而且这两个子类是存在关系的
(他们的区别参考:Factory Method模式与Abstract Factory模式区别1,2)
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
来管理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反射机制如下: 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到的两个个例子(1,2)是一种完全不同的处理方式,也是一个写C++的同学推荐的方法
简单工厂类维护一个对象名称到对象实例的映射
工厂方法基类里面有个静态createInstance函数,然后每个子类继承这个createInstance函数,每个子类的createInstance自己实例化自己一个实例,在外面函数调用基类的createInstance,非常简单就实例化一个子类
3. 简单工厂维护name到实例的映射
{ // store instances of pools
private static Map
new HashMap
// 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
#include
#include
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::map
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;
}