设计模式之经验交流 :Abstract Factory, Template Style(0分)

  • 主题发起人 主题发起人 VRGL
  • 开始时间 开始时间
V

VRGL

Unregistered / Unconfirmed
GUEST, unregistred user!
设计模式之经验交流 :Abstract Factory, Template Style

作者:Jim Hyslop and Herb Sutter(HolyFire翻译)

文章来源:www.cuj.com
上一篇 下一篇

--------------------------------------------------------------------------------
写于2001年, Jim Hyslop and Herb Sutter
------------------------------------------------------------------------------------------
--------------------------------------------------------------------
我向倚着金属靠椅坐在我们面前的设计师比划着说:"我们该如何理解这个呢?"他用极快的眼神将我审
视了一遍然后将视线投向远方,当时我觉得好像陷入了冰窖一般。
Jeannine摇了摇头。"不明白吗?同志。他可以是一个胜利者,一个火箭推进器,一个宝宝的玩具,也
可以是一个舢板。我想我们下个星期就要完成动力系统,就是这个以及其他的设计,但是我们运行这个
废物时这些玩艺从头到尾什么也没干。设计院的设计图上这些设计一直到动力运作,但是设计师们却希
望他们能尽快得到正确的结果"
"是什么让他们有这样的想法?"
"只是个期望而已"
我瞥了一眼墙上的钟。"现在到好,这么紧迫的时间,我想我不行了,我无法进行下去了。每次我们向
视察小组要求新的工作的时候,他们总是提供一些新的不同的工作,我只是希望他们能理解工作上需要
一些连贯性"
Jeannine似乎赞同我的观点"我想在这里我们更能理解一点展现在我们面前的过去使用的Abstract
factory.
"这使我想起了曾经经历过的那件事----"
Jeannine闪动着智慧的双眼"告诉我那个让我们激动的时刻"
------------------------------------------------------------------------------------------
--------------------------------------------------------------------
"坏消息!"我招呼着卧室隔壁闷闷不乐的Wendy。
"怎么了"她窜了起来。
"你知道我上个星期使用的class吗"
"不是很清楚,不过他正在运作"
"很好"我打断了她继续说道"我为它作了一个class factory。Guru启示我将这个class factory做成客
户群的需要。
"是这样啊"她的脸上闪过一片阴罹:"但是Bob完成了它,不是吗?"
我郁闷的点点头"唯一值得庆幸的事是,我取得了他的信任----任何时候我都可以改进他的代码,我知
道什么时候有些事不该作" Wendy哈哈一笑又倒在她的椅子里了。
我叹了口气埋头察看那些个源代码去了。这些代码不象我预计的那样糟糕,他们只是一个巨大的if语句
的一层层的嵌套-----我更想的是看到更多的毛病,但是他还是那个只是一堆杂乱的代码。Guru保佑,
我看到了实现Abstract Class Factory的影子。在缺少需求和杂乱无章的情况下,我决定将factory实
现成一个singleton:
class BaseFactory
{
typedef std::auto_ptr (*BaseCreateFn)();
typedef std::map FnRegistry;
FnRegistry registry;

BaseFactory() {}
BaseFactory(const BaseFactory &);
// Not implemented
BaseFactory &
operator=(const BaseFactory &);
// Not implemented
public:
static BaseFactory &
instance() { static BaseFactory bf;
return bf;
}
bool RegCreateFn(const std::string &, BaseCreateFn);

std::auto_ptr Create(const std::string &) const;
};

bool BaseFactory::RegCreateFn(const std::string &
className, BaseCreateFn fn)
{
registry[className] = fn;
return true;
}
std::auto_ptr BaseFactory::Create(const std::string &className) const
{
std::auto_ptr theObject(0);
FnRegistry::const_iterator regEntry = registry.find(className);
if (regEntry != registry.end())
{
theObject = regEntry->second();
}
return theObject;
}
在基类实现文件里,我加上了:
namespace
{
std::auto_ptr CreateBase()
{
return std::auto_ptr(new Base);
}
bool dummy = BaseFactory::instance().RegCreateFn("Base", CreateBase);
}
"太酷了!"我想道"你使用factory来注册一个函数,他将创建一个实例,one, two, three,就这么简
单"
int main()
{
std::auto_ptr anObject = BaseFactory::instance().Create("Base");
}
我接着派生了一个类,用来测试用这个factory创建。
在派生类实现文件里,我加上了:
namespace
{
std::auto_ptr CreateDerived()
{
return std::auto_ptr(new Derived);
}
bool dummy = BaseFactory::instance().RegCreateFn("Derived", CreateDerived);
}
但是编译器罢工了----他一直抱怨CreateDerived不能转化正确的类型。迷惑了一阵后,我想起了这个
问题,我先前的经验告诉我将指针转化为BASE是正确的选择。我认识到我刚刚陷入了另一个问题,编译
器不能隐含的转化指针。所以我重写了创建函数部分:
namespace
{
std::auto_ptr CreateDerived()
{
return std::auto_ptr(new Derived);
}
bool dummy = BaseFactory::instance().RegCreateFn("Derived", CreateDerived);
}
#define REGISTER_CLASS(BASE_CLASS, DERIVED_CLASS) namespace { std::auto_ptr
Create##DERIVED_CLASS() { return std::auto_ptr(new DERIVED_CLASS);

} bool dummy=BaseFactory::instance().RegCreateFn( #DERIVED_CLASS,
Create##DERIVED_CLASS);
}
使用这个宏就简单多了
REGISTER_CLASS(Base, Base)
"这几个小时收获不错"完成后我喃喃说道。
"真的吗,我的小菜鸟,不过我能作的更好"
"哇-"Guru柔和的声音却差点让我跳起来。
"像这样展开宏"她不紧不慢的解释道"是很难以阅读和理解的,而且宏不是类型安全的。而且,这个
bool型的变量dummy有什么用意呢?"
"是这样的"我些微的为自己辩护,"只有这样我才能确保注册函数被自动调用了。我想抛弃传统factory
编码那需要在每加入一个新类的时候都要进行修改”
她转过脸来"英明的想法,我的小菜鸟。但是,你的factory还不是很通用。我们对待越来越多的类的时
候需要用的是abstract factories。我想要你建立一个factory,他将这样处理,没有要求,可以被它
的子类修改,那它将更常用"
"一个通用的abstract factory?多么离奇的要求,不是吗?"
"我的小学生,你根本不惧挑战,对吗?经验是从工作中得来的…,熟能生巧啊"
我结束了她发言"不,我不能为了熟能生巧把进度放在一边啊"
"你总是走那些老套路。你最需要的不是考虑通用吗"她坚持着。
"考虑通用性,那不就是,模板!"我突然一呼而出立刻转向显示器,几分钟后,我深怕Guru悄悄的消失
正如她悄悄的出现,我不禁有些颤抖,但是很快就进入了工作状态。
短短一瞬间,我完成了factory template:
template
class GenericFactory
{
typedef std::auto_ptr (*BaseCreateFn)();
typedef std::map FnRegistry;
FnRegistry registry;

GenericFactory();
GenericFactory(const GenericFactory&);
// Not implemented
GenericFactory &operator=(const GenericFactory&);
// Not implemented
public:
static GenericFactory &instance();

void RegCreateFn(const ClassIDKey &, BaseCreateFn);

std::auto_ptr Create(const ClassIDKey &className) const;
};
我认识到不是所有的类用到了std::string这个key,所以我将这个key做成了参数的形式。每个函数的
实现我都用到了BaseFactory,除了注册函数。我使用了更多的好用的tempalte:
template
class RegisterInFactory
{
public:
static std::auto_ptr CreateInstance()
{
return std::auto_ptr(new ManufacturedType);
}
RegisterInFactory(const ClassIDKey &id)
{
GenericFactory::instance().RegCreateFn(id, CreateInstance);
}
};
现在,每个从这个类派生的类都简单的加上了一个类型安全的内联的注册函数用来创建:
RegisterInFactory registerMe("Base");
这个RegisterInFactorytempalte的构造函数注册了类名
我向后偷偷瞄了一眼,正好看到Guru走过来,在她这个竞赛里略占上风,我不禁得意洋洋。
"非常好,我的学生,"她走到我后面时发话了"你的factory通用了,很便捷,不依赖注册表,DLL以及
其他繁琐的技术。"
"尽管如此这里还有一点缺陷"我打断了她的话"因为注册依赖一个静态对象的初始化,使用这个factory
他还不能保证所有的创建函数都能在main执行前被注册"
"非常正确,我的学生,你的factory受到了静态对象初始化次序的影响是一大败笔,就像先知Cline解
释的一样"她开始准备离开。
"请等一会儿"我挽留道。Guru转了回来。我开始努力砌词来完美的表达我想询问的意图。Guru很有耐心
在一边整理头发。"比方说Bob。如果他写了一堆糟糕的程式,"我开始笨拙的拼凑胡言乱语"他开始…"
"那为何他还留在这里?"Guru补充道。我点点头。Guru陷入了沉思。
"你有没有注意到Bob测试的成绩很突出?高层的管理员认为他是一个难得的人才因为他很少出错。因为
我们…恩啊…算了,Bob深的他们信任,所以我即使有所抱怨也是无济于事。还有,看看他,人人都买
我的帐除了他,他总和我不一致"
"天哪,这一定不好受。你怎能容忍这些?你可以找到别的工作"我握着她的手。
她耸耸肩。"除了Bob,我还是很喜欢这里。此外,如果我离开了,还真找不到他这样能让我满意的找到
bug并解决的人呢"
我们相视而笑。"说真的,尽管如此"她继续说道"这个公司有很多机会发展的。比方说,我们的新临床
分割系统在软件业处于领先水平----我已在这方面有应用了。"酷!祝你好运"我祝福道。Guru颔首以示
谢意。我回到工作室,完成abstract factory template这一杰作的收尾工作。
------------------------------------------------------------------------------------------
--------------------------------------------------------------------
消息到来的这几天我都干到很晚,不干完这些明天我又不知道什么时候就要爬起来。正当我睡眼朦胧的
时候,我走进混乱不堪的工作室时一些不寻常的杂乱声引起了我的注意,我将手放在额头上窥视
者。"是什么这么吵?"我不满的嘀咕着,这时有十二个人正在那儿,兴奋的交谈着。
"你这个家伙这么早就完成了,相当有自信啊"
这是一个叫Major Gilb对我说的话,他正在向我微笑"我想我们成功了,我的小伙子,我们做到了!"
"什么?"我丈二摸不着头脑。
"你看,动力已经开动了" Jeannine轻描淡写的说道。

 
最近作一个试题设计器,主要是(单选,多选,阅读理解.完形填空...),试题保存成文件
而且要生成试卷.
我用了一个Factory
一个父类Question(有个成员ID,可以用于判断题型),以及单选,多选,阅读理解.完形填空四个子类,
窗体为MDI的,对应四种childform,每种和一个题型邦在一起(题型作为childform的成员),
这样数据与表示分离,当安规则生成试卷时,只要建立题型对象就可以了
还有一些成员比如出题人,题目附加信息,难度应该放在Question,还是他的子类
还有每个题型子类都有一个tofile的方法,是应该放在父类然后子类中覆盖还是只加在子类
想听听大家的意见
 
出题人,题目附加信息,难度应该放在Question中,
放在子类中会有重复代码,
tofile的方法在Question类中设为纯虚函数,
然后在子类中覆盖它
 
有什么好的工具能把能设计关系模型,并把他映射到Java表示的对象模型??
 
together6.0
可以将UML图实时生成Java,C++,IDL等代码,同时可生成各种模式(GOF,CORBA,EJB等)的框架代码
 
接受答案了.
 

Similar threads

后退
顶部