kdl问题见:http://www.kuqin.com/design-patterns/20071113/2300.html;
问题转为代码描述如下:
// =====================================================================================
//
// Filename: kdl.cpp
//
// Description: keyboard display log
//
// Version: 1.0
// Created: 10/24/2012 11:19:23 AM
// Revision: none
// Compiler: g++
//
// =====================================================================================
#include <stdio.h>
#include <stdlib.h>
class Log
{
public:
static Log &instance()
{
static Log inst;
return inst;
}
void log(const char *str)
{
printf("[%d]: %s\n", working, str);
}
private:
Log()
{
printf("Log()\n");
working = 1;
}
Log(const Log &);
Log &operator=(const Log &);
~Log()
{
printf("~Log()\n");
working = 0;
}
private:
int working;
};
class Keyboard
{
public:
static Keyboard &instance()
{
static Keyboard inst;
return inst;
}
private:
Keyboard()
{
printf("Keyboard()\n");
}
Keyboard(const Keyboard &);
Keyboard &operator=(const Keyboard &);
~Keyboard()
{
printf("~Keyboard()\n");
Log::instance().log("keyboard destruct error");
}
};
class Display
{
public:
static Display &instance()
{
static Display inst;
return inst;
}
private:
Display()
{
printf("Display()\n");
Log::instance().log("display construct error");
exit(-1);
}
Display(const Display &);
Display &operator=(const Display &);
~Display()
{
printf("~Display()\n");
}
};
int main(int argc, char *argv[])
{
Keyboard &k = Keyboard::instance();
Display &d = Display::instance();
return 0;
}
程序输出:
Keyboard()
Display()
Log()
[1]: display construct error
~Log()
~Keyboard()
[0]: keyboard destruct error
如果在实现Log时采用pimpl方式,也就是说构造Log时代价不大,真正使用时,才去new impl,同时也保证Log的单例先于Keyboard和Display构造,问题就解决了。
代码示例如下:
// =====================================================================================
//
// Filename: kdl.cpp
//
// Description: keyboard display log
//
// Version: 1.0
// Created: 10/24/2012 11:19:23 AM
// Revision: none
// Compiler: g++
//
// =====================================================================================
#include <stdio.h>
#include <stdlib.h>
class LogImpl
{
public:
LogImpl()
{
printf("LogImpl()\n");
}
~ LogImpl()
{
printf("~LogImpl()\n");
}
void log(const char *str, int working)
{
printf("[%d]: %s\n", working, str);
}
};
class Log
{
public:
static Log &instance()
{
static Log inst;
return inst;
}
void log(const char *str)
{
if (!impl)
{
impl = new LogImpl;
}
impl->log(str, working);
}
private:
Log()
{
printf("Log()\n");
working = 1;
impl = NULL;
}
Log(const Log &);
Log &operator=(const Log &);
~Log()
{
working = 0;
if (impl)
{
delete impl;
impl = NULL;
}
printf("~Log()\n");
}
private:
int working;
LogImpl *impl;
};
class Keyboard
{
public:
static Keyboard &instance()
{
static Keyboard inst;
return inst;
}
private:
Keyboard()
{
printf("Keyboard()\n");
}
Keyboard(const Keyboard &);
Keyboard &operator=(const Keyboard &);
~Keyboard()
{
printf("~Keyboard()\n");
Log::instance().log("keyboard destruct error");
}
};
class Display
{
public:
static Display &instance()
{
static Display inst;
return inst;
}
private:
Display()
{
printf("Display()\n");
Log::instance().log("display construct error");
exit(-1);
}
Display(const Display &);
Display &operator=(const Display &);
~Display()
{
printf("~Display()\n");
}
};
int main(int argc, char *argv[])
{
Log &l = Log::instance();
Keyboard &k = Keyboard::instance();
Display &d = Display::instance();
return 0;
}
程序输出:
Log()
Keyboard()
Display()
LogImpl()
[1]: display construct error
~Keyboard()
[1]: keyboard destruct error
~LogImpl()
~Log()