﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Richard He-文章分类-设计模式</title><link>http://www.cppblog.com/richardhe/category/7785.html</link><description>学无止境!永远学下去!</description><language>zh-cn</language><lastBuildDate>Mon, 08 Dec 2008 14:32:46 GMT</lastBuildDate><pubDate>Mon, 08 Dec 2008 14:32:46 GMT</pubDate><ttl>60</ttl><item><title>成员函数指针与高性能的C++委托</title><link>http://www.cppblog.com/richardhe/articles/68829.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Mon, 08 Dec 2008 03:50:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/68829.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/68829.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/68829.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/68829.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/68829.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 引子标准C++中没有真正的面向对象的函数指针。这一点对C++来说是不幸的，因为面向对象的指针（也叫做&#8220;闭包（closure）&#8221;或&#8220;委托（delegate）&#8221;）在一些语言中已经证明了它宝贵的价值。在Delphi (Object Pascal)中，面向对象的函数指针是Borland可视化组建库（VCL，Visual Component Library...&nbsp;&nbsp;<a href='http://www.cppblog.com/richardhe/articles/68829.html'>阅读全文</a><img src ="http://www.cppblog.com/richardhe/aggbug/68829.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-12-08 11:50 <a href="http://www.cppblog.com/richardhe/articles/68829.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式（一）</title><link>http://www.cppblog.com/richardhe/articles/58160.html</link><dc:creator>RichardHe</dc:creator><author>RichardHe</author><pubDate>Wed, 06 Aug 2008 08:36:00 GMT</pubDate><guid>http://www.cppblog.com/richardhe/articles/58160.html</guid><wfw:comment>http://www.cppblog.com/richardhe/comments/58160.html</wfw:comment><comments>http://www.cppblog.com/richardhe/articles/58160.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/richardhe/comments/commentRss/58160.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/richardhe/services/trackbacks/58160.html</trackback:ping><description><![CDATA[出自http://www.cppblog.com/Fox/archive/2008/08/06/58154.html<br>
<div class="postbody">
<p><strong><font color="#800000">0. Introduction</font></strong></p>
<p>接触设计模式有两年时间了，但一直没有系统整理过，为了不至于让自己的思维被繁琐的工作一点点禁锢，还是决定总结一下，为了能够真正做到有所收获，整个系列会按照<a  href="http://en.wikipedia.org/wiki/Gang_of_Four_%28software%29" title="Gang of four" target="_blank">GoF的Design Patterns: Elements of Reusable Object-Oriented Software</a>的行文思路，但不会照本宣科就是了，<a  href="http://www.wikipedia.org/" title="Wikipedia" target="_blank">Wikipedia</a>上关于23种设计模式的介绍非常全面，CSDN上也可以下载中/英文电子档，因此很多套话、类图一概省去。</p>
<p>最早接触设计模式的时候，难免被各种模式的联系和区别所困扰，从教科书的分析可以得到模式之间形式上的不同。但这样对于领会设计模式意义不大，因为我们掌握模式的目的是为了融会贯通，灵活运用，以对开发有所帮助。</p>
<p>稍微成规模的OO程序，会有大量对象，其中很多实体对象之间存在着<strong>父子、兄弟</strong>关系，对象的<strong>创建</strong>提升为一种模式。其好处在于设计模式本身所宣称的<strong>reusable</strong>，这就像堆积木盖房子一样，堆的好的情况下，换一换门窗便是另一番风景。</p>
<p>关于实现，我不会为了厘清模式间的区别而刻意使用相似代码实现，相反，我会根据模式本身的适用情况举例，而且大量代码基于<a  href="http://sourcemaking.com/design_patterns" title="http://sourcemaking.com/design_patterns" target="_blank">SourceMaking</a>。</p>
<p>_______________________________</p>
<p><strong><font color="#800000">1. Creational Design Patterns(DP)</font></strong></p>
<p>创建型DP抽象了类和对象的创建过程，<a  href="http://en.wikipedia.org/wiki/Gang_of_Four_%28software%29" title="Gang of four" target="_blank">GoF</a>给出了5种<strong>创建型DP</strong>：<strong>Abstract Factory</strong>、<strong>Builder</strong>、<strong>Factory Method</strong>、<strong>Builder</strong>、<strong>Prototype</strong>、<strong>Singleton</strong>。</p>
<p><strong><font color="#800000">2. Abstract Factory</font></strong></p>
<p><strong>意图：提供一个创建一系列相关或相互依赖对象的接口，而无需指定它们具体的类。</strong></p>
<p>1) 只提供了一个创建接口，其返回值为具体产品：如<code>AbstractProduct *Client::CreateProduct(AbstractFactory &amp;factory);</code></p>
<p>2) 接口的参数是一个<strong>工厂对象</strong>（<code>AbstractFactory &amp;factory</code>）的引用，参数类型（<code>AbstractFactory</code>）为抽象基类，调用时根据需要传入具体工厂对象即可；</p>
<p>3) 接口内部实现了<strong>一系列相关或相互依赖对象</strong>（抽象产品）的创建：当传入具体工厂时，接口实现的就是<strong>一系列具体产品</strong>的创建；</p>
<p>4) 创建的产品<strong>立即返回</strong>（<code>CreateProduct</code>）。</p>
<p><strong>参与者：</strong></p>
<p>&#8226; AbstractFactory<br>— 声明一个创建抽象产品对象的操作接口。</p>
<p>&#8226; ConcreteFactory<br>— 实现创建具体产品对象的操作。</p>
<p>&#8226; AbstractProduct<br>— 为一类产品对象声明一个接口。</p>
<p>&#8226; ConcreteProduct<br>— 定义一个将被相应的具体工厂创建的产品对象。<br>— 实现AbstractProduct接口。</p>
<p>&#8226; Client<br>— 仅使用由AbstractFactory和AbstractProduct类声明的接口。</p>
<p><strong>代码：</strong></p>
<code> </code>
<p>class AbstractFactory<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual AbstractProduct *MakePartA() = 0;<br>&nbsp;&nbsp;&nbsp; virtual AbstractProduct *MakePartB() = 0;<br>&nbsp;&nbsp;&nbsp; virtual AbstractProduct *MakePartC() = 0;<br>&nbsp;&nbsp;&nbsp; virtual AbstractProduct *AddPart(const AbstractProduct *pPart) = 0;<br>};  </p>
<p>AbstractProduct *Client::CreateProduct(AbstractFactory &amp;factory)<br>{<br>&nbsp;&nbsp;&nbsp; AbstractProduct *pProduct = factory.CreateProduct();<br>&nbsp;&nbsp;&nbsp; AbstractProduct *pPartA = factory.MakePartA();<br>&nbsp;&nbsp;&nbsp; AbstractProduct *pPartB = factory.MakePartB();<br>&nbsp;&nbsp;&nbsp; AbstractProduct *pPartC = factory.MakePartC();<br>&nbsp;&nbsp;&nbsp; factory.AddPart(pPartA);<br>&nbsp;&nbsp;&nbsp; factory.AddPart(pPartB);<br>&nbsp;&nbsp;&nbsp; factory.AddPart(pPartC);<br>&nbsp;&nbsp;&nbsp; return pProduct;<br>} </p>
<p>int main(void)<br>{<br>&nbsp;&nbsp;&nbsp; Client client;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ConcreteFactory factory;<br>&nbsp;&nbsp;&nbsp; client.CreateProduct(factory);<br>&nbsp;&nbsp;&nbsp; return 0;<br>}  </p>
<p><strong><font color="#800000">3. Builder</font></strong></p>
<p><strong>意图：将一个复杂对象的构建与它的表示分离，使得同样的构建过程可以创建不同的表示。</strong></p>
<p>1) director提供抽象产品创建接口：如<code>void Director::Construct();</code></p>
<p>2) 不同产品使用<strong>同一创建过程</strong>，由director指定特定builder以生产不同产品；</p>
<p>3) 接口内部实现了<strong>一个复杂对象</strong>（抽象产品）的创建：当传入具体工厂时，接口实现的是<strong>一个复杂的具体产品</strong>的创建；</p>
<p>4) 创建的产品<strong>并不立即返回</strong>，<strong>创建完毕</strong>后返回，或<strong>使用接口</strong>（<code>GetProduct</code>）提取结果。</p>
<p><strong>参与者：</strong></p>
<p>&#8226; Builder<br>— 为创建一个Product对象的各个部件指定抽象接口。</p>
<p>&#8226; ConcreteBuilder<br>— 实现Builder的接口以构造和装配该产品的各个部件。<br>— 定义并明确它所创建的表示。<br>— 提供一个检索产品的接口。</p>
<p>&#8226; Director<br>— 构造一个使用Builder接口的对象。</p>
<p>&#8226; Product<br>— 表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。<br>— 包含定义组成部件的类，包括将这些部件装配成最终产品的接口。</p>
<p><strong>代码：</strong></p>
<code> </code>
<p>class Builder<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual void MakePartA() = 0;<br>&nbsp;&nbsp;&nbsp; virtual void MakePartB() = 0;<br>&nbsp;&nbsp;&nbsp; virtual void MakePartC() = 0;  </p>
<p>&nbsp;&nbsp;&nbsp; Product *GetProduct()&nbsp;&nbsp;&nbsp; { return _product; }  </p>
<p>protected:<br>&nbsp;&nbsp;&nbsp; Product *_product;<br>};  </p>
<p>class Director<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; void setBuilder(Builder *b)&nbsp;&nbsp;&nbsp; { _builder = b; }<br>&nbsp;&nbsp;&nbsp; void Construct();  </p>
<p>private:<br>&nbsp;&nbsp;&nbsp; Builder *_builder;<br>};  </p>
<p>void Director::Construct()<br>{<br>&nbsp;&nbsp;&nbsp; _builder.MakePartA();<br>&nbsp;&nbsp;&nbsp; _builder.MakePartB();<br>&nbsp;&nbsp;&nbsp; _builder.MakePartC();<br>}  </p>
<p>int main(void) {<br>&nbsp;&nbsp;&nbsp; ConcreteBuilderA concreteBuilderA;<br>&nbsp;&nbsp;&nbsp; ConcreteBuilderB concreteBuilderB;<br>&nbsp;&nbsp;&nbsp; Director director;<br>&nbsp;&nbsp;&nbsp; Product *pProduct;  </p>
<p>&nbsp;&nbsp;&nbsp; director.SetBuilder(&amp;concreteBuilderA);<br>&nbsp;&nbsp;&nbsp; director.Construct();<br>&nbsp;&nbsp;&nbsp; pProduct = concreteBuilderA.GetProduct();<br>&nbsp;&nbsp;&nbsp; pProduct-&gt;Show();  </p>
<p>&nbsp;&nbsp;&nbsp; director.SetBuilder(&amp;concreteBuilderB);<br>&nbsp;&nbsp;&nbsp; director.Construct();<br>&nbsp;&nbsp;&nbsp; pProduct = concreteBuilderB.GetProduct();<br>&nbsp;&nbsp;&nbsp; pProduct-&gt;Show();  </p>
<p>&nbsp;&nbsp;&nbsp; return 0;<br>}</p>
<p><strong><font color="#800000">4. Factory Method</font></strong></p>
<p><strong>意图：定义一个用于创建对象的接口，让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类。</strong></p>
<p>1) 看得出该模式其实就是<strong>C++的多态特性</strong>，借<strong>继承</strong>实现。因此，其别名为<strong>虚构造器（ Virtual Constructor）</strong>；</p>
<p>2) 作为模式与C++多态特性不同的是，Creator可以定义<strong>工厂方法的缺省实现</strong>，完成缺省操作，MFC大量使用了这一思想。</p>
<p><strong>参与者：</strong></p>
<p>&#8226; Product<br>— 定义工厂方法所创建的对象的接口。</p>
<p>&#8226; ConcreteProduct<br>— 实现Product接口。</p>
<p>&#8226; Creator<br>— 声明工厂方法，该方法返回一个Product类型的对象。Creator也可以定义一个工厂方法的缺省实现，它返回一个缺省的ConcreteProduct对象。<br>— 可以调用工厂方法以创建一个Product对象。</p>
<p>&#8226; ConcreteCreator<br>— 重定义工厂方法以返回一个ConcreteProduct实例。</p>
<p><strong>代码：</strong></p>
<p><code>ConcreteProduct *ConcreteCreator::FactoryMethod()<br>{<br>&nbsp;&nbsp;&nbsp; <code>ConcreteProduct</code> *pProduct = new <code>ConcreteProduct</code>;<br>&nbsp;&nbsp;&nbsp; return pProduct;<br>}</code></p>
<p><code>Product *Creator::FactoryMethod()<br>{<br>&nbsp;&nbsp;&nbsp; Product *pProduct = new Product;<br>&nbsp;&nbsp;&nbsp; return pProduct;<br>} </code></p>
<p>int main(void) {<br>&nbsp;&nbsp;&nbsp; Creator creator;<br>&nbsp;&nbsp;&nbsp; ConcreteProduct *pProduct;  </p>
<p>&nbsp;&nbsp;&nbsp; pProduct = creator.FactoryMethod();<br>&nbsp;&nbsp;&nbsp; pProduct-&gt;Show();  </p>
<p>&nbsp;&nbsp;&nbsp; return 0;<br>}  </p>
<p><strong><font color="#800000">5. Prototype</font></strong></p>
<p><strong>意图：用原型实例指定创建对象的种类，并且通过拷贝这些原型创建新的对象。</strong></p>
<p>1) 创建不再通过工厂新类<strong>继承（inheritance）</strong>，而是通过<strong>委托（delegation）</strong>；</p>
<p>2) 根通<strong>拷贝原型实例</strong>创建新对象。</p>
<p><strong>参与者：</strong></p>
<p>&#8226; ProtoType<br>— 声明一个克隆自身的接口。</p>
<p>&#8226; ConcreteProtoType<br>— 实现一个克隆自身的操作。</p>
<p>&#8226; Client<br>— 让一个原型克隆自身从而创建一个新的对象。</p>
<p><strong>代码：</strong></p>
<code> </code>
<p>class ProtoType<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual void Draw();<br>&nbsp;&nbsp;&nbsp; virtual ProtoType *Clone() = 0;<br>&nbsp;&nbsp;&nbsp; virtual void Initialize();<br>};  </p>
<p>class ProtoTypeA: public ProtoType<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; virtual ProtoType *Clone()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new ProtoTypeA;<br>&nbsp;&nbsp;&nbsp; }<br>};  </p>
<p>class ProtoTypeB: public ProtoType<br>{ <br>public:<br>&nbsp;&nbsp;&nbsp; virtual ProtoType *Clone()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new ProtoTypeB;<br>&nbsp;&nbsp;&nbsp; }<br>};  </p>
<p>class Client<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; static ProtoType *Clone( int choice );  </p>
<p>private:<br>&nbsp;&nbsp;&nbsp; static ProtoType *s_prototypes[3];<br>};  </p>
<p>ProtoType* Client::s_prototypes[] = { 0, new ProtoTypeA, new ProtoTypeB };  </p>
<p>ProtoType *Client::Clone(int choice)<br>{<br>&nbsp;&nbsp;&nbsp; return s_prototypes[choice]-&gt;Clone();<br>}  </p>
<p><strong><font color="#800000">6. Singleton</font></strong></p>
<p><strong>意图：保证一个类仅有一个实例，并提供一个访问它的全局访问点。</strong></p>
<p>1) 用<strong>静态成员函数</strong>保证上述意图。</p>
<p><strong>参与者：</strong></p>
<p>&#8226; Singleton<br>— 定义一个Instance操作，允许客户访问它的唯一实例。Instance是一个类操作（即C++中的一个静态成员函数）。<br>— 可能负责创建它自己的唯一实例。</p>
<p><strong>代码：</strong></p>
<code> </code>
<p>class Singleton<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; static Singleton *GetInstance()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!s_instance)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s_instance = new Singleton;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return s_instance;<br>&nbsp;&nbsp;&nbsp; }  </p>
<p>&nbsp;&nbsp;&nbsp; void Run()&nbsp;&nbsp;&nbsp; {}  </p>
<p>private:<br>&nbsp;&nbsp;&nbsp; static Singleton *s_instance;<br>&nbsp;&nbsp;&nbsp; Singleton()&nbsp;&nbsp;&nbsp; {}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Singleton cannot be created outside.<br>};  </p>
<p>Singleton *GetSingleton(void)<br>{<br>&nbsp;&nbsp;&nbsp; return Singleton::GetInstance();<br>}  </p>
<p>int main(void)<br>{<br>&nbsp;&nbsp;&nbsp; GetSingleton()-&gt;Run();  </p>
<p>&nbsp;&nbsp;&nbsp; return 0;<br>}</p>
<p>______________________________________________</p>
<p>代码写的都比较简单，基本可以将各种模式之间的不同体现出来了。</p>
</div>
<br><img src ="http://www.cppblog.com/richardhe/aggbug/58160.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/richardhe/" target="_blank">RichardHe</a> 2008-08-06 16:36 <a href="http://www.cppblog.com/richardhe/articles/58160.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>