<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>夜游长空 &#187; 学习</title>
	<atom:link href="http://www.zhangdi.name/tag/%e5%ad%a6%e4%b9%a0/feed" rel="self" type="application/rss+xml" />
	<link>http://www.zhangdi.name</link>
	<description>Blog of Daniel &#38; Kimi</description>
	<lastBuildDate>Wed, 13 Oct 2010 05:05:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>用40行程序能展示多少Ruby的特性？</title>
		<link>http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html</link>
		<comments>http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html#comments</comments>
		<pubDate>Wed, 22 Aug 2007 07:27:40 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html</guid>
		<description><![CDATA[module OutputHelper def print_line(msg) print msg + "\\n" end end class SayHello include OutputHelper private :print_line def initialize(name, &#38;sayHello) @name, @sayHello = name, sayHello if @sayHello == nil @sayHello = proc { &#124;msg&#124; print_line msg } end end def salute(greet_msg) @sayHello.call("Hello, #{@name}. #{greet_msg}.") end def salute_with_block(greet_msg) if block_given? yield "Hello, #{@name}. I'm using a block. [...]]]></description>
			<content:encoded><![CDATA[<p><!--ruby develop 编程 开发--></p>
<pre name="code" class="ruby">
module OutputHelper
  def print_line(msg)
    print msg + "\\n"
  end
end

class SayHello
  include OutputHelper
  private :print_line
  def initialize(name, &amp;sayHello)
    @name, @sayHello = name, sayHello

    if @sayHello == nil
      @sayHello = proc { |msg| print_line msg }
    end
  end

  def salute(greet_msg)
    @sayHello.call("Hello, #{@name}. #{greet_msg}.")
  end

  def salute_with_block(greet_msg)
    if block_given?
      yield "Hello, #{@name}. I'm using a block. #{greet_msg}."
    else
      @sayHello.call("Hello, #{@name}. You missed the block. #{greet_msg}.")
    end
  end
end

if __FILE__ == $0
  say_hello = SayHello.new("Daniel") { |msg| print msg + "\\n" }
  say_hello.salute("Greetings")
  say_hello.salute_with_block("Greetings")
  say_hello.salute_with_block("Greetings") { |msg| print msg + "\\n" }

  say_hello = SayHello.new("Kimi")
  say_hello.salute("Greetings, again")
end</pre>
<ul>
<li>定义module以及class。</li>
<li>Mixin，将一个module动态include到class里面，使之具有相应的功能。</li>
<li>method的访问级别，private, public等。很多动态语言没有这个功能。</li>
<li>向构造函数传入block类型的参数。</li>
<li>用proc方法构造block。</li>
<li>用block.call方法，调用一个block类型的变量。</li>
<li>用block_given?方法判断是否为一个方法传入了block参数。</li>
<li>用yield来调用为方法传入的block参数。</li>
<li>将测试代码写在if __FILE__ = $0 &#8230; end块中。很类似于Python。</li>
<li>用{|params| expressions }形式定义block。</li>
</ul>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html" title="Ruby: puts != print + &#8220;\n&#8221;">Ruby: puts != print + &#8220;\n&#8221;</a></li><li><a href="http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html" title="当Ruby遇到数独">当Ruby遇到数独</a></li><li><a href="http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html" title="VC++2005 StringTable资源类型研究">VC++2005 StringTable资源类型研究</a></li><li><a href="http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html" title="不用代码和类图说设计模式（2）">不用代码和类图说设计模式（2）</a></li><li><a href="http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html" title="不用代码和类图说设计模式（1）">不用代码和类图说设计模式（1）</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Ruby: puts != print + &#8220;\n&#8221;</title>
		<link>http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html</link>
		<comments>http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html#comments</comments>
		<pubDate>Tue, 21 Aug 2007 14:18:36 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[源码分析]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/08/21/ruby-puts-print-n.html</guid>
		<description><![CDATA[今天看到railschina论坛上一篇贴子在讨论在Ruby中，puts str是不是等于print str + &#8220;\n&#8221;。因为一位同学做了实验，在irb中，在多线程环境下使用puts似乎有问题，有的时候字符串和换行的顺序会乱，而用print就没有问题，所以得出结论，认为puts是不等于print + &#8220;\n&#8221;的。又有人提出质疑，因为做了另外的实验，在非irb环境下，puts和print都没有问题，所以认为多线程问题只是主观臆测，有可能是irb的问题。甚至还有人写信给Dave，结果Dave也没有给出明确的答复～ 正好手头上有Ruby的源代码，所以翻出来看了一下，在io.c中，明确的写明了Ruby中ios.puts方法的实现： VALUE rb_io_puts(argc, argv, out) int argc; VALUE *argv; VALUE out; { int i; VALUE line; /* if no argument given, print newline. */ if (argc == 0) { rb_io_write(out, rb_default_rs); return Qnil; } for (i=0; i&#60;argc; i++) { if (NIL_P(argv[i])) { line = rb_str_new2("nil"); } else { [...]]]></description>
			<content:encoded><![CDATA[<p><!--ruby develop 编程 开发--></p>
<p>今天看到railschina论坛上一篇贴子在讨论在Ruby中，puts str是不是等于print str + &#8220;\n&#8221;。因为一位同学做了实验，在irb中，在多线程环境下使用puts似乎有问题，有的时候字符串和换行的顺序会乱，而用print就没有问题，所以得出结论，认为puts是不等于print + &#8220;\n&#8221;的。又有人提出质疑，因为做了另外的实验，在非irb环境下，puts和print都没有问题，所以认为多线程问题只是主观臆测，有可能是irb的问题。甚至还有人写信给Dave，结果Dave也没有给出明确的答复～</p>
<p>正好手头上有Ruby的源代码，所以翻出来看了一下，在io.c中，明确的写明了Ruby中ios.puts方法的实现：</p>
<pre name="code" class="cpp:collapse">
VALUE
rb_io_puts(argc, argv, out)
    int argc;
    VALUE *argv;
    VALUE out;
{
   int i;
   VALUE line; 

   /* if no argument given, print newline. */
   if (argc == 0) {
      rb_io_write(out, rb_default_rs);
      return Qnil;
   }
   for (i=0; i&lt;argc; i++) {
      if (NIL_P(argv[i])) {
         line = rb_str_new2("nil");
      }
      else {
         line = rb_check_array_type(argv[i]);
         if (!NIL_P(line)) {
            rb_protect_inspect(io_puts_ary, line, out);
            continue;
         }
         line = rb_obj_as_string(argv[i]);
      }
      rb_io_write(out, line);
      if (RSTRING(line)-&gt;len == 0 ||
            RSTRING(line)-&gt;ptr[RSTRING(line)-&gt;len-1] != '\n') {
         rb_io_write(out, rb_default_rs);
      }
   } 

   return Qnil;
}</pre>
<p>可以看到27行和30行就是分别向流中写我们传入的string和&#8221;\n&#8221;的代码，所以puts确实是<strong>存在潜在的多线程问题</strong>的。而对于print str + &#8220;\n&#8221;这种方式，因为ruby会先把str和&#8221;\n&#8221;构造为一个新的string，然后再传给print函数，所以是没有这种问题的。总结：在Ruby中，<strong>puts != print + &#8220;\n&#8221;</strong></p>
<p>另外，如果用print(str1, str2)这种形式，同样会有多线程问题。因为在Ruby中，print的实现是，一个一个参数分别写入流，而不是先将参数合并，再一次写入。（合并参数会占用额外的内存，多次IO又会消耗时间，不知道最初Ruby是如何权衡这个的～）</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html" title="用40行程序能展示多少Ruby的特性？">用40行程序能展示多少Ruby的特性？</a></li><li><a href="http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html" title="当Ruby遇到数独">当Ruby遇到数独</a></li><li><a href="http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html" title="VC++2005 StringTable资源类型研究">VC++2005 StringTable资源类型研究</a></li><li><a href="http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html" title="不用代码和类图说设计模式（2）">不用代码和类图说设计模式（2）</a></li><li><a href="http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html" title="不用代码和类图说设计模式（1）">不用代码和类图说设计模式（1）</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VC++2005 StringTable资源类型研究</title>
		<link>http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html</link>
		<comments>http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html#comments</comments>
		<pubDate>Mon, 21 May 2007 15:32:21 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Windows]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Windows编程]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[编程]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html</guid>
		<description><![CDATA[在来到新公司之前，对于Windows编程实在不熟悉，更别说VC++中的Resource的实现了。工作的时候，同事提到了StringTable实现本地化的问题。当时我也很模糊，说不出个准确答案。周末回家研究了两天，算是搞明白了。 先说说我之前比较困惑的几个问题： 在编译完成的二进制文件中，StringTable到底是按照什么方式存储的，简单说，就是按照什么编码方式存储的？ Windows已经支持了Unicode，为什么在VC++的StringTable Editor中，还要选择语言？ 如果使用了Unicode，怎么有的时候，应用程序还会出现乱码？ 如果是Unicode编码，那么是按照什么格式存储的，UTF-8，UTF-16？ 当然，对于这些问题，可能对于一些牛人来说不算什么，都是很简单的问题。不过，对于我来说，还是很麻烦的，因为网上没有很直接解释这些问题的文章，最终还是自己一点一点研究出来的。 首先，需要复习和学习一些知识： 在计算机诞生的初期，操作系统只支持最多256个字符，就是著名的ASCII字符集。但是随着计算机在世界上各个国家的发展，本地化的需求越来越多，256个字符明显不够，就有一些国家发明了自己的字符集，也可以说是编码标准，不过这些编码方式都是只考虑自己国家的语言（当然不会有一个国家为了发展自己的科技，还要替别人着想），比如，ISO-8859-1，GB2312等等，在Windows里面，这类编码的体现就是我们熟悉的Code Page。在VC++中，Code Page是使用数字来代表的，比如：936是简体中文Code Page，1256是阿拉伯语言的Code Page。这样显然不爽，随着计算机的普及，Code Page会越来越多，并且很多Code Page可能相差不多，但是为了支持相应的用户，应用程序（包括操作系统）就不得不对之提供支持，这大大提高了软件的成本。终于，一些软件业的巨头决定做一件一劳永逸的事情，就是创造一个字符编码方式，能支持世界上所有的字符，这个字符集编码叫做Unicode。它设计可以支持11万多的字符，被认为足够放下世界上已知的所有字符（其中，中文字符占了2万多，英文只占52个）。而我们经常看到的UTF-8，UTF-16，UTF-32都是Unicode的一种存储方式。 言归正传，回答自己的四个问题： 从Windows2000开始，Windows已经完全支持了Unicode，所以StringTable在二进制文件（*.dll、*.exe）中确实是以Unicode编码存储的。 在StringTable Editor中，之所以要为StringTable选择相应的语言，是因为StringTable Editor中不是以Unicode存储的，而是基于Code Page编码存储的。所以必须对自己的StringTable选择正确的Code Page，否则系统将不能正确处理。因为在编译的时候，VC++的Resource Compiler会自动调用MultiByteToWideChar这个API，将字符串从Code Page编码方式转化为Unicode，如果Code Page选择不正确，那么转换也就必然不正确了。 出现乱码一个原因是操作系统不支持Unicode，比如Windows98之前的版本。或者是没有将默认编码设置为Unicode。 在Windows中都是使用UTF-16来存储Unicode的。UTF-16正好是两个字节，也就是我们使用的WCHAR类型。 需要说的是，StringTable Editor不是使用Unicode来存储，是因为历史原因。早期的VC++是不支持Unicode的。 相关文章Windows Box Model解析用40行程序能展示多少Ruby的特性？Ruby: puts != print + &#8220;\n&#8221;《Windows核心编程》&#8211; 经典的书，翻译太烂不用代码和类图说设计模式（2）]]></description>
			<content:encoded><![CDATA[<p><!--VC++ develop StringTable 开发 Windows编程 编程--></p>
<p>在来到新公司之前，对于Windows编程实在不熟悉，更别说VC++中的Resource的实现了。工作的时候，同事提到了StringTable实现本地化的问题。当时我也很模糊，说不出个准确答案。周末回家研究了两天，算是搞明白了。</p>
<p>先说说我之前比较困惑的几个问题：</p>
<ul>
<li>在编译完成的二进制文件中，StringTable到底是按照什么方式存储的，简单说，就是按照什么编码方式存储的？</li>
<li>Windows已经支持了Unicode，为什么在VC++的StringTable Editor中，还要选择语言？</li>
<li>如果使用了Unicode，怎么有的时候，应用程序还会出现乱码？</li>
<li>如果是Unicode编码，那么是按照什么格式存储的，UTF-8，UTF-16？</li>
</ul>
<p>当然，对于这些问题，可能对于一些牛人来说不算什么，都是很简单的问题。不过，对于我来说，还是很麻烦的，因为网上没有很直接解释这些问题的文章，最终还是自己一点一点研究出来的。</p>
<p>首先，需要复习和学习一些知识：</p>
<p>在计算机诞生的初期，操作系统只支持最多256个字符，就是著名的ASCII字符集。但是随着计算机在世界上各个国家的发展，本地化的需求越来越多，256个字符明显不够，就有一些国家发明了自己的字符集，也可以说是编码标准，不过这些编码方式都是只考虑自己国家的语言（当然不会有一个国家为了发展自己的科技，还要替别人着想），比如，ISO-8859-1，GB2312等等，在Windows里面，这类编码的体现就是我们熟悉的Code Page。在VC++中，Code Page是使用数字来代表的，比如：936是简体中文Code Page，1256是阿拉伯语言的Code Page。这样显然不爽，随着计算机的普及，Code Page会越来越多，并且很多Code Page可能相差不多，但是为了支持相应的用户，应用程序（包括操作系统）就不得不对之提供支持，这大大提高了软件的成本。终于，一些软件业的巨头决定做一件一劳永逸的事情，就是创造一个字符编码方式，能支持世界上所有的字符，这个字符集编码叫做Unicode。它设计可以支持11万多的字符，被认为足够放下世界上已知的所有字符（其中，中文字符占了2万多，英文只占52个）。而我们经常看到的UTF-8，UTF-16，UTF-32都是Unicode的一种存储方式。</p>
<p>言归正传，回答自己的四个问题：</p>
<ul>
<li>从Windows2000开始，Windows已经完全支持了Unicode，所以StringTable在二进制文件（*.dll、*.exe）中确实是以Unicode编码存储的。</li>
<li>在StringTable Editor中，之所以要为StringTable选择相应的语言，是因为StringTable Editor中不是以Unicode存储的，而是基于Code Page编码存储的。所以必须对自己的StringTable选择正确的Code Page，否则系统将不能正确处理。因为在编译的时候，VC++的Resource Compiler会自动调用MultiByteToWideChar这个API，将字符串从Code Page编码方式转化为Unicode，如果Code Page选择不正确，那么转换也就必然不正确了。</li>
<li>出现乱码一个原因是操作系统不支持Unicode，比如Windows98之前的版本。或者是没有将默认编码设置为Unicode。</li>
<li>在Windows中都是使用UTF-16来存储Unicode的。UTF-16正好是两个字节，也就是我们使用的WCHAR类型。</li>
</ul>
<p>需要说的是，StringTable Editor不是使用Unicode来存储，是因为历史原因。早期的VC++是不支持Unicode的。</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/07/17/explain-windows-box-model.html" title="Windows Box Model解析">Windows Box Model解析</a></li><li><a href="http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html" title="用40行程序能展示多少Ruby的特性？">用40行程序能展示多少Ruby的特性？</a></li><li><a href="http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html" title="Ruby: puts != print + &#8220;\n&#8221;">Ruby: puts != print + &#8220;\n&#8221;</a></li><li><a href="http://www.zhangdi.name/2007/08/16/programming-applications-for-microsoft-windows.html" title="《Windows核心编程》&#8211; 经典的书，翻译太烂">《Windows核心编程》&#8211; 经典的书，翻译太烂</a></li><li><a href="http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html" title="不用代码和类图说设计模式（2）">不用代码和类图说设计模式（2）</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>不用代码和类图说设计模式（2）</title>
		<link>http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html</link>
		<comments>http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html#comments</comments>
		<pubDate>Sun, 18 Mar 2007 08:29:07 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[设计模式]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html</guid>
		<description><![CDATA[设计模式，实际上是一些很标准的算法解决方案，如果对于一个很常见的问题，一个人使用了设计模式中的方法解决，当别人看代码的时候，也会很爽快。而如果没有，那看代码的人就会很疑惑，问题明明可以很明确的使用某种设计模式解决，那为什么原来是这样的呢？是不是有什么tricky的地方，不得不这样写？无形中延长了时间，并且增加了维护时出问题的机会。 我觉得知道各个模式所表达的算法实现各个设计模式所需要的算法还算容易，而明确的知道什么时候该用什么模式就比较难了。我也经常写出自己后悔的代码来：在写过代码后，review的时候，突然发现，其实可以用更好的方法解决问题。这就是refactoring的作用了吧。呵呵。 二、Singleton, Builder, Prototype模式 这三个模式仍然是关系到对象创建的，但这三个模式特点都很明确，比较容易找到适应的情形。再来讲三个故事： 1、从前，有一个小姑娘叫“春”（这是我高中的时候，一个同学作文中经典的句子，很难忘记~）。我们叫她“春姑娘”吧。有一天她在海边散步的时候，见到了一个油灯，上面写着“Singleton”，小姑娘很好奇，就轻轻摸了一下这些字，突然从灯里面出来了一个灯神，他跟小姑娘说：“谢谢你帮我解除了咒语，我现在自由了。只要你拿着这个灯，什么时候叫一句‘Singleton’，我都会出来。” 小姑娘有些犹豫，我不会喊来坏蛋吧？这个灯我又不熟悉。灯神大笑，这个灯叫“Singleton”，所以每次出来的都只能是我，不会是别人的。甚至替身都不会有。小姑娘高兴的回家了。 2、其实，小姑娘在家里很苦。受到继母的虐待。每天都要做饭，洗衣服，挑水，天不亮就要干活，一直要干到深夜。这天晚上，终于干完了活，睡觉之前，她把灯神交出来，想跟他聊聊天。因为她找不到别人聊天了，能找到的只有这个向她承诺过的灯神了。她把她的苦恼都跟灯神说了，灯神很同情她。（其实，这个灯神就是天界众神派来帮助小姑娘的）临走的时候，送给小姑娘一口锅，上面写着Builder这个单词。小姑娘不解，我现在还有锅啊。灯神说，这个锅是天界众神使用的锅，它的最大特点就是不用人干预就可以做出饭菜。你只需要按照这个菜谱往锅里放进原料，盖上盖子，等一会再打开，就是香喷喷的饭菜了。说着给了小姑娘一本菜谱。 3、自从有了那口神奇的锅，小姑娘的劳累减轻了很多，继母很生气。她又命令小姑娘每天要到海边钓鱼，而且必须钓到十种鱼，每一种鱼100条，这100条鱼必须颜色重量形状都要一样，否则不算。小姑娘哭着说：“这不可能啊~“ 继母狠狠地说：”怎么不可能，钓不完就别回家！“ 小姑娘来到海边，坐在岸上哭了起来。这时，灯神又神秘的出现了。他送给小姑娘一根鱼竿，并说，这个鱼竿是天界众神的鱼竿，这个鱼竿叫&#8217;Prototype&#8217;（天界众神是研究Design Pattern的~），只要是它钓到的鱼，你只要喊：”Clone!“ 就会复制出一个跟这条鱼各个方面都一样的鱼。最终，美丽善良的小姑娘在灯神的帮助下，通过水晶鞋事件，与王子结为夫妻，过上了幸福的生活。 这三个模式从字面上都可以看出来是做什么用的： Singleton Pattern: 中文叫”单件“，顾名思义，就是说只允许有一个实例的对象，而且无论在哪里都可以拿到这个实例。优点是最简单的满足了单一实例的要求，不足之处就是，在哪里都可以拿到，就跟静态变量一样，容易让程序混乱，而且对多线程也是一个挑战。 Builder Pattern: 隐藏构造复杂对象的过程，用户只需要将构建复杂对象的基础对象提供给Builder，就可以得到最终的结果。我们用的输入法实际上就是一种Builder。 Prototype Pattern: 这个模式对于现实生活来说，有些神奇（现在也不是了，因为有了克隆技术），但是对于写程序来说，应该不陌生了。Java, C#等等，都内置了这个Pattern，那就是对象的Clone方法。可以通过一个原形对象，创建出一个与之状态完全一样的对象。与Factory不一样的地方就是，能够保证状态。 创建型模式一共六个，就复习完了。用了一个周末的时间（两个半天）。 Update：一位兄弟指出我把算法和设计模式混淆了。我想了一下，确实是不妥，因为设计模式是在设计阶段考虑的问题，而算法是在实现阶段考虑的问题，不应该混为一谈。不过设计的如何，最终要使用算法来实现。所以我认为设计模式和实现它的算法是密不可分的（否则就不会有那么多本书分别介绍C#, Java等等中的Design Pattern了），而且对于一个开发人员来说，设计和开发更是紧密结合的。 相关文章不用代码和类图说设计模式（1）用40行程序能展示多少Ruby的特性？Ruby: puts != print + &#8220;\n&#8221;VC++2005 StringTable资源类型研究当Ruby遇到数独]]></description>
			<content:encoded><![CDATA[<p>设计模式，实际上是一些很标准的<strike>算法</strike>解决方案，如果对于一个很常见的问题，一个人使用了设计模式中的方法解决，当别人看代码的时候，也会很爽快。而如果没有，那看代码的人就会很疑惑，问题明明可以很明确的使用某种设计模式解决，那为什么原来是这样的呢？是不是有什么tricky的地方，不得不这样写？无形中延长了时间，并且增加了维护时出问题的机会。</p>
<p>我觉得知道<strike>各个模式所表达的算法</strike>实现各个设计模式所需要的算法还算容易，而明确的知道什么时候该用什么模式就比较难了。我也经常写出自己后悔的代码来：在写过代码后，review的时候，突然发现，其实可以用更好的方法解决问题。这就是refactoring的作用了吧。呵呵。</p>
<p>二、Singleton, Builder, Prototype模式</p>
<p>这三个模式仍然是关系到对象创建的，但这三个模式特点都很明确，比较容易找到适应的情形。再来讲三个故事：</p>
<p>1、从前，有一个小姑娘叫“春”（这是我高中的时候，一个同学作文中经典的句子，很难忘记~）。我们叫她“春姑娘”吧。有一天她在海边散步的时候，见到了一个油灯，上面写着“Singleton”，小姑娘很好奇，就轻轻摸了一下这些字，突然从灯里面出来了一个灯神，他跟小姑娘说：“谢谢你帮我解除了咒语，我现在自由了。只要你拿着这个灯，什么时候叫一句‘Singleton’，我都会出来。” 小姑娘有些犹豫，我不会喊来坏蛋吧？这个灯我又不熟悉。灯神大笑，这个灯叫“Singleton”，所以每次出来的都只能是我，不会是别人的。甚至替身都不会有。小姑娘高兴的回家了。</p>
<p>2、其实，小姑娘在家里很苦。受到继母的虐待。每天都要做饭，洗衣服，挑水，天不亮就要干活，一直要干到深夜。这天晚上，终于干完了活，睡觉之前，她把灯神交出来，想跟他聊聊天。因为她找不到别人聊天了，能找到的只有这个向她承诺过的灯神了。她把她的苦恼都跟灯神说了，灯神很同情她。（其实，这个灯神就是天界众神派来帮助小姑娘的）临走的时候，送给小姑娘一口锅，上面写着Builder这个单词。小姑娘不解，我现在还有锅啊。灯神说，这个锅是天界众神使用的锅，它的最大特点就是不用人干预就可以做出饭菜。你只需要按照这个菜谱往锅里放进原料，盖上盖子，等一会再打开，就是香喷喷的饭菜了。说着给了小姑娘一本菜谱。</p>
<p><span id="more-178"></span></p>
<p>3、自从有了那口神奇的锅，小姑娘的劳累减轻了很多，继母很生气。她又命令小姑娘每天要到海边钓鱼，而且必须钓到十种鱼，每一种鱼100条，这100条鱼必须颜色重量形状都要一样，否则不算。小姑娘哭着说：“这不可能啊~“ 继母狠狠地说：”怎么不可能，钓不完就别回家！“ 小姑娘来到海边，坐在岸上哭了起来。这时，灯神又神秘的出现了。他送给小姑娘一根鱼竿，并说，这个鱼竿是天界众神的鱼竿，这个鱼竿叫&#8217;Prototype&#8217;（天界众神是研究Design Pattern的~），只要是它钓到的鱼，你只要喊：”Clone!“ 就会复制出一个跟这条鱼各个方面都一样的鱼。最终，美丽善良的小姑娘在灯神的帮助下，通过水晶鞋事件，与王子结为夫妻，过上了幸福的生活。</p>
<p>这三个模式从字面上都可以看出来是做什么用的：</p>
<p><strong>Singleton</strong> Pattern: 中文叫”单件“，顾名思义，就是说只允许有一个实例的对象，而且无论在哪里都可以拿到这个实例。优点是最简单的满足了单一实例的要求，不足之处就是，在哪里都可以拿到，就跟静态变量一样，容易让程序混乱，而且对多线程也是一个挑战。</p>
<p><strong>Builder</strong> Pattern: 隐藏构造复杂对象的过程，用户只需要将构建复杂对象的基础对象提供给Builder，就可以得到最终的结果。我们用的输入法实际上就是一种Builder。</p>
<p><strong>Prototype</strong> Pattern: 这个模式对于现实生活来说，有些神奇（现在也不是了，因为有了克隆技术），但是对于写程序来说，应该不陌生了。Java, C#等等，都内置了这个Pattern，那就是对象的Clone方法。可以通过一个原形对象，创建出一个与之状态完全一样的对象。与Factory不一样的地方就是，能够保证状态。</p>
<p>创建型模式一共六个，就复习完了。用了一个周末的时间（两个半天）。</p>
<p><font color="#ff0000">Update：一位兄弟指出我把算法和设计模式混淆了。我想了一下，确实是不妥，因为设计模式是在设计阶段考虑的问题，而算法是在实现阶段考虑的问题，不应该混为一谈。不过设计的如何，最终要使用算法来实现。所以我认为设计模式和实现它的算法是密不可分的（否则就不会有那么多本书分别介绍C#, Java等等中的Design Pattern了），而且对于一个开发人员来说，设计和开发更是紧密结合的。</font></p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html" title="不用代码和类图说设计模式（1）">不用代码和类图说设计模式（1）</a></li><li><a href="http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html" title="用40行程序能展示多少Ruby的特性？">用40行程序能展示多少Ruby的特性？</a></li><li><a href="http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html" title="Ruby: puts != print + &#8220;\n&#8221;">Ruby: puts != print + &#8220;\n&#8221;</a></li><li><a href="http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html" title="VC++2005 StringTable资源类型研究">VC++2005 StringTable资源类型研究</a></li><li><a href="http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html" title="当Ruby遇到数独">当Ruby遇到数独</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>不用代码和类图说设计模式（1）</title>
		<link>http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html</link>
		<comments>http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html#comments</comments>
		<pubDate>Sat, 17 Mar 2007 10:40:02 +0000</pubDate>
		<dc:creator>zhangdi</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[学习]]></category>
		<category><![CDATA[编程]]></category>
		<category><![CDATA[设计模式]]></category>

		<guid isPermaLink="false">http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-classes-diagram-1.html</guid>
		<description><![CDATA[最近在重新学习C++，也在看公司产品的代码，深切体会到一个大型的项目如果没有很好的代码设计，会为维护带来过大的成本。我想说的代码设计，并不是产品层次的设计，而是developer在写程序的时候，如何设计自己实现功能所使用的编码方式和模式。这就是为什么我突然决定复习设计模式了。我看设计模式还是在大学，虽然多少还有些印象，但真正能拿起来用的就那么几种经常用到的。但设计模式是针对不同问题的不同best practice，所以如果有一种不知道，就可能在coding的时候走弯路，甚至走错路。 我希望能把我复习的过程写成一系列的文章，而且不想用代码和类图来说明，因为这些东西在所有介绍设计模式的书里面都很多，我只想把我复习的心得和问题写出来。难免有错误，希望任何人指出。:) 一、Factory, Abstract Factory, Factory Method模式 这三个模式都跟Factory这个词有关系，所以都是用来创建对象的模式。我最初看到这三个模式的时候，真是有点晕，都是factory，有什么区别呢？在什么时候需要用哪个呢？ 先来讲三个故事： 1、一个匪徒，我们叫他Mr. Pattern，为了要实施对一个银行进行抢劫，需要买一支武器。但他不知道买什么，所以他来到了一家叫&#8221;WeaponFactory&#8221;的武器店。他说了他想要武器后，营业员说，我们这里有A系列手枪、B系列手枪、A系列自动步枪、B系列自动步枪甚至还有Z系列火箭筒，你想要什么就去相应的柜台交钱，然后就可以拿到货了。 2、还是这个Mr. Pattern，他决定不在&#8221;WeaponFactory&#8221;买了，因为那里武器全都摆在一起，太多了，导致店铺太大，根本就没办法逛，而且据说后来因为无法再扩大营业面积最终倒闭了。这次他来到了一个叫“AbstractWeaponFactory”的店。他这回多了个心眼，透着窗户看了看，恩，这回里面不是很乱，好像店里面就摆了一个系列的产品。他不知道这个系列是不是他需要的，抱着试试看的想法，他踏入了店门。突然，一阵眩晕，等再清醒过来，看到面前摆的都是C系列的产品：手枪、步枪等等。这时，一位美丽的导购小姐走过来，对Mr. Pattern说：“感谢您的光临，我们已经根据您的需求和所处的环境，将您自动传送到我们的C系列子店中，在这里您可以买到所有您需要的产品”。Mr. Pattern幸福的晕过去。 3、Mr. Pattern经历过&#8221;AbstractWeaponFactory&#8221;的美好体验并且成功使用C系列产品打劫了一家银行后，在业内非常出名。他现在有钱了，想要点高级货。这次他来到一个名字叫“FactoryMethod Weapon”的店铺。这里的东西似乎没有什么特别的，当Mr. Pattern正要离开的时候，发现每个武器上都有一个小按钮，上面写着“弹药”。难道武器可以自己提供弹药？他按了一下手枪上的，果然有手枪子弹从一个枪身侧面一个隐秘的小口一颗一颗的挤出，正好装满一个弹夹的数量。他又按了一下步枪上的，这次直接从枪托中弹出一个完整的弹夹。Mr. Pattern很兴奋，他不怀好意的又按了一下火箭筒的，似乎没有什么反应，哈哈，也有不灵的，突然这时，门外响起汽车急停的声音，冲进来一个人，这个人全副武装，怀里抱着一颗火箭弹。 这三个故事并不是想说哪个店铺经营最成功，而是想分别举例说明Factory, Abstract Factory和Factory Method三个设计模式的特点。 Factory Pattern: 简单的构造对象。优点是简单，封装对象的构造过程。通过配置和参数，可以某种程度替代Abstract Factory的工作。缺点是只能应对简单的情形，复杂的情况下，很容易导致代码冗长，有太多的条件判断等等。 Abstract Factory Pattern: 根据情景，构建一组关联的对象。优点是: 结构清晰，每个系列的对象在不同的concrete factory中，每次用户只能拿到一个concrete factory, 所以不会有混用的情形。缺点，每多一个系列都要有一个相对应的concrete factory。 Factory Method Pattern: 将创建的操作交给子类来做。比如说，我们要弹药，是写一个Factory来提供各个型号的弹药呢；还是写一个Abstract Factory来根据我们手中的武器得到相应系列的concrete factory，再通过相对应的方法来得到弹药呢；还是我们跟武器说，我们要弹药，然后这个武器自己给你了呢。这就是Factory Method。优点是，提供一个逻辑很清晰的创建对象的接口。缺点是，每个子类都要实现Factory Method，所以当子类过多并且需要创建的对象的种类也过多的时候，就应该考虑使用Abstract Factory来解决问题了。 总结一下，Factory就是简单的创建对象，确实一定要简单，越复杂的情形，就越应该用别的模式；Abstract Factory是针对需要构造的对象明确的分为几个系列，GoF中使用family，我觉得很确切。需要另外的机制，使用户透明的得到concrete factory，比如，配置文件，系统参数等等；Factory Method针对要构造的对象明确的与子类相关。比如，武器的“获得弹药”这步构造，明确地与子类相关，每种武器都不一样，所以我们就把构造的任务交给各个子类，当然，如果不光要弹药，我还要各种零件，那就还不如提供一个资源箱（Abstract Factory）。不过，话说回来，具体情况具体分析。就像具体编码的时候，Factory Method可能是通过Abstract Factory实现的，而Abstract Factory可能通过Factory组成。总之，面对一个问题，找到最适合的模式，那就是高手了。 [...]]]></description>
			<content:encoded><![CDATA[<p><!--develop C++ design pattern talk 设计模式 经验 学习--></p>
<p>最近在重新学习C++，也在看公司产品的代码，深切体会到一个大型的项目如果没有很好的代码设计，会为维护带来过大的成本。我想说的代码设计，并不是产品层次的设计，而是developer在写程序的时候，如何设计自己实现功能所使用的编码方式和模式。这就是为什么我突然决定复习设计模式了。我看设计模式还是在大学，虽然多少还有些印象，但真正能拿起来用的就那么几种经常用到的。但设计模式是针对不同问题的不同best practice，所以如果有一种不知道，就可能在coding的时候走弯路，甚至走错路。</p>
<p>我希望能把我复习的过程写成一系列的文章，而且不想用代码和类图来说明，因为这些东西在所有介绍设计模式的书里面都很多，我只想把我复习的心得和问题写出来。难免有错误，希望任何人指出。:)</p>
<p>一、Factory, Abstract Factory, Factory Method模式</p>
<p>这三个模式都跟Factory这个词有关系，所以都是用来创建对象的模式。我最初看到这三个模式的时候，真是有点晕，都是factory，有什么区别呢？在什么时候需要用哪个呢？</p>
<p>先来讲三个故事：</p>
<p>1、一个匪徒，我们叫他Mr. Pattern，为了要实施对一个银行进行抢劫，需要买一支武器。但他不知道买什么，所以他来到了一家叫&#8221;WeaponFactory&#8221;的武器店。他说了他想要武器后，营业员说，我们这里有A系列手枪、B系列手枪、A系列自动步枪、B系列自动步枪甚至还有Z系列火箭筒，你想要什么就去相应的柜台交钱，然后就可以拿到货了。</p>
<p>2、还是这个Mr. Pattern，他决定不在&#8221;WeaponFactory&#8221;买了，因为那里武器全都摆在一起，太多了，导致店铺太大，根本就没办法逛，而且据说后来因为无法再扩大营业面积最终倒闭了。这次他来到了一个叫“AbstractWeaponFactory”的店。他这回多了个心眼，透着窗户看了看，恩，这回里面不是很乱，好像店里面就摆了一个系列的产品。他不知道这个系列是不是他需要的，抱着试试看的想法，他踏入了店门。突然，一阵眩晕，等再清醒过来，看到面前摆的都是C系列的产品：手枪、步枪等等。这时，一位美丽的导购小姐走过来，对Mr. Pattern说：“感谢您的光临，我们已经根据您的需求和所处的环境，将您自动传送到我们的C系列子店中，在这里您可以买到所有您需要的产品”。Mr. Pattern幸福的晕过去。</p>
<p><span id="more-176"></span></p>
<p>3、Mr. Pattern经历过&#8221;AbstractWeaponFactory&#8221;的美好体验并且成功使用C系列产品打劫了一家银行后，在业内非常出名。他现在有钱了，想要点高级货。这次他来到一个名字叫“FactoryMethod Weapon”的店铺。这里的东西似乎没有什么特别的，当Mr. Pattern正要离开的时候，发现每个武器上都有一个小按钮，上面写着“弹药”。难道武器可以自己提供弹药？他按了一下手枪上的，果然有手枪子弹从一个枪身侧面一个隐秘的小口一颗一颗的挤出，正好装满一个弹夹的数量。他又按了一下步枪上的，这次直接从枪托中弹出一个完整的弹夹。Mr. Pattern很兴奋，他不怀好意的又按了一下火箭筒的，似乎没有什么反应，哈哈，也有不灵的，突然这时，门外响起汽车急停的声音，冲进来一个人，这个人全副武装，怀里抱着一颗火箭弹。</p>
<p>这三个故事并不是想说哪个店铺经营最成功，而是想分别举例说明Factory, Abstract Factory和Factory Method三个设计模式的特点。</p>
<p><strong>Factory</strong> Pattern: 简单的构造对象。优点是简单，封装对象的构造过程。通过配置和参数，可以某种程度替代Abstract Factory的工作。缺点是只能应对简单的情形，复杂的情况下，很容易导致代码冗长，有太多的条件判断等等。</p>
<p><strong>Abstract Factory</strong> Pattern: 根据情景，构建一组关联的对象。优点是: 结构清晰，每个系列的对象在不同的concrete factory中，每次用户只能拿到一个concrete factory, 所以不会有混用的情形。缺点，每多一个系列都要有一个相对应的concrete factory。</p>
<p><strong>Factory Method</strong> Pattern: 将创建的操作交给子类来做。比如说，我们要弹药，是写一个Factory来提供各个型号的弹药呢；还是写一个Abstract Factory来根据我们手中的武器得到相应系列的concrete factory，再通过相对应的方法来得到弹药呢；还是我们跟武器说，我们要弹药，然后这个武器自己给你了呢。这就是Factory Method。优点是，提供一个逻辑很清晰的创建对象的接口。缺点是，每个子类都要实现Factory Method，所以当子类过多并且需要创建的对象的种类也过多的时候，就应该考虑使用Abstract Factory来解决问题了。</p>
<p>总结一下，Factory就是简单的创建对象，确实一定要简单，越复杂的情形，就越应该用别的模式；Abstract Factory是针对需要构造的对象明确的分为几个系列，GoF中使用family，我觉得很确切。需要另外的机制，使用户透明的得到concrete factory，比如，配置文件，系统参数等等；Factory Method针对要构造的对象明确的与子类相关。比如，武器的“获得弹药”这步构造，明确地与子类相关，每种武器都不一样，所以我们就把构造的任务交给各个子类，当然，如果不光要弹药，我还要各种零件，那就还不如提供一个资源箱（Abstract Factory）。不过，话说回来，具体情况具体分析。就像具体编码的时候，Factory Method可能是通过Abstract Factory实现的，而Abstract Factory可能通过Factory组成。总之，面对一个问题，找到最适合的模式，那就是高手了。</p>
<h3  class="related_post_title">相关文章</h3><ul class="related_post"><li><a href="http://www.zhangdi.name/2007/03/18/learn-design-pattern-without-coding-and-class-diagram-2.html" title="不用代码和类图说设计模式（2）">不用代码和类图说设计模式（2）</a></li><li><a href="http://www.zhangdi.name/2007/08/22/a-piece-of-ruby-code.html" title="用40行程序能展示多少Ruby的特性？">用40行程序能展示多少Ruby的特性？</a></li><li><a href="http://www.zhangdi.name/2007/08/21/ruby-puts-not-equals-print-plus-back-slash-n.html" title="Ruby: puts != print + &#8220;\n&#8221;">Ruby: puts != print + &#8220;\n&#8221;</a></li><li><a href="http://www.zhangdi.name/2007/05/21/research-on-stringtable-in-vcpp.html" title="VC++2005 StringTable资源类型研究">VC++2005 StringTable资源类型研究</a></li><li><a href="http://www.zhangdi.name/2007/09/06/when-ruby-meets-sudoku.html" title="当Ruby遇到数独">当Ruby遇到数独</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.zhangdi.name/2007/03/17/learn-design-pattern-without-coding-and-class-diagram-1.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

