<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_倪大虾</title><subtitle type="text">在有限的时间里呈现无限的精彩</subtitle><id>http://feed.cnblogs.com/blog/u/72274/rss</id><updated>2011-11-24T14:40:58Z</updated><author><name>倪大虾</name><uri>http://www.cnblogs.com/niyw/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/niyw/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/72274/rss"/><entry><id>http://www.cnblogs.com/niyw/archive/2011/06/02/2064937.html</id><title type="text">高效管理ASP.NET的JavaScript库</title><summary type="text">本文提供了一种非常高效的管理ASP.NET网站JS脚本的一种方法。</summary><published>2011-06-02T01:29:00Z</published><updated>2011-06-02T01:29:00Z</updated><author><name>倪大虾</name><uri>http://www.cnblogs.com/niyw/</uri></author><link rel="alternate" href="http://www.cnblogs.com/niyw/archive/2011/06/02/2064937.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/niyw/archive/2011/06/02/2064937.html"/><content type="html">&lt;p&gt;&lt;strong&gt;简介&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;对于ASP.NET开发人员来说,管理项目中的JavaScript都很随意：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011053117150934.png" /&gt;&lt;/p&gt;&lt;p&gt;我想这很大程度上可能是因为网上没有如何妥善处理ASP.NET中JavaScript的可靠信息。此文的目的就是提供一种最佳方案，用于管理ASP.NET中的JavaScript。该方案将能解决以下问题：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;内联JS&lt;/strong&gt;：把JS直接放在页面中将导致页面臃肿不堪。 &lt;/li&gt;&lt;li&gt;&lt;strong&gt;发布JS&lt;/strong&gt;：经常忘记发布JS文件。 &lt;/li&gt;&lt;li&gt;&lt;strong&gt;错误引用&lt;/strong&gt;：在其它Web程序中引用JS时经常失败。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;依赖性&lt;/strong&gt;：需要记住JS文件中错综复杂的依赖关系。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;无效引用&lt;/strong&gt;：页面上引用的JS从来没有被用到。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;HTTP/HTTPS&lt;/strong&gt;：跨HTTPS页面引用HTTP的JS。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;重构&lt;/strong&gt;：重构一个新版本将花费大量时间。 &lt;/li&gt;&lt;li&gt;&lt;strong&gt;冗余&lt;/strong&gt;：多次引用统一个JS文件。&lt;/li&gt;&lt;/ul&gt;&lt;h2 id="prerequisites"&gt;预备知识&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;确保已安装Visual Studio 2010。Express版可能不支持此文涉及到的一些概念。&lt;/p&gt;&lt;h2 id="overview"&gt;概述&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;大部分上述问题是由把JS或JS文件引用直接放到ASPX页面引起的。对几乎所有上述问题的解决方法是使用ASP.NET的内置功能来嵌入JS文件到一个DLL，然后动态引用这些文件。本文将演示这些功能，以及一些充分使用它们的技巧。接下来我们将逐步介绍该如何实现。&lt;/p&gt;&lt;h2 id="getting_started"&gt;开始&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;第一步，启动Visual Studio 2010,并新建一个名为&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;ParchmentPurveyor&lt;/span&gt;的&lt;/code&gt;空Web程序。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011053117475863.png" /&gt;&lt;/p&gt;&lt;p&gt;接下来添加一个窗体：Default.aspx，并添加一些简单的HTML代码。大致如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;@ Page Language&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;C#&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; AutoEventWireup&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;true&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; CodeBehind&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;Default.aspx.cs&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;&lt;br /&gt;    Inherits&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;ParchmentPurveyor.Default&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; &lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;html &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;head &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;runat&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="server"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Parchment Purveyor&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;form &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="form1"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; runat&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="server"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;h1&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Parchment Purveyor&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;h1&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Paper for printers, painting, publication,&lt;br /&gt;            paper planes, and plenty of other plebeian projects!&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;form&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;添加JS&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;不同于在站点中添加JS文件，我们新建一个项目，用于包含我们所有的JS文件。在解决方案中添加一个新的类库项目&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;JavaScriptLibrary&lt;/span&gt;：&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011053118023273.png" /&gt;&lt;/p&gt;&lt;p&gt;项目添加后删除Class1.cs文件，右键项目，选择添加文件夹，并命名为JavaScript，然后在该文件夹中添加两个JS文件，分别为ShowMessage.js和GreetUser.js，下一步，在项目中添加一个类&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;JavaScriptHelper&lt;/span&gt;（注意不要放到&lt;/code&gt;JavaScript目录下&lt;code lang="text"&gt;），现在解决方案目录结构如下：&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011053120334944.png" /&gt;&lt;/p&gt;&lt;p&gt;接下来编写JS，在ShowMessage.js中添加如下代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; ShowMessage(msg) {&lt;br /&gt;    alert(&lt;/span&gt;&lt;span style="color: #000000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;Message From Website: &lt;/span&gt;&lt;span style="color: #000000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; msg);&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在GreetUser.js文件中添加如下代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="color: #000000;"&gt; GreetUser() {&lt;br /&gt;    ShowMessage(&lt;/span&gt;&lt;span style="color: #000000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;Greetings and Salutations!&lt;/span&gt;&lt;span style="color: #000000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;注意，&lt;span style="color: #993300;"&gt;GreetUser()&lt;/span&gt;依赖于&lt;span style="color: #993300;"&gt;ShowMessage()&lt;/span&gt;。&lt;/p&gt;&lt;h2 id="embedding_javascript"&gt;嵌入JS文件&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;相比把JS文件发布到站点，我们更乐于把它们嵌入到DLL。这样子，如果DLL被发布到站点，那么所有JS文件也被自动发布。做到一点很简单，我们只需要右键JS文件，打开属性页，为&amp;ldquo;&lt;span style="color: #993300;"&gt;生成操作&lt;/span&gt;&amp;rdquo;选择&amp;ldquo;&lt;span style="color: #993300;"&gt;嵌入资源&lt;/span&gt;&amp;rdquo;即可，如下：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011053120431048.png" /&gt;&lt;/p&gt;&lt;p&gt;在确定JS文件嵌入DLL后，你需要使它们能够被Web用户访问。为此，需要为项目&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;JavaScriptLibrary&lt;/span&gt;添加&lt;/code&gt;&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;System.Web&lt;/span&gt;的引用：&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011053120455723.png" /&gt;&lt;/p&gt;&lt;p&gt;然后编辑&lt;span style="color: #993300;"&gt;JavaScriptHelper.cs&lt;/span&gt;,添加如下代码：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web.UI;&lt;br /&gt;&lt;br /&gt;[assembly: WebResource(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JavaScriptLibrary.JavaScript.ShowMessage.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;application/x-javascript&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;[assembly: WebResource(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JavaScriptLibrary.JavaScript.GreetUser.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;application/x-javascript&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;这样就能保证Web用户通过客户端访问嵌入式JS文件了。&lt;/p&gt;&lt;h2 id="including_embedded_javascript"&gt;引用嵌入式JS文件&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;现在你已嵌入了JS文件，并能通过客户端电脑访问它们。在使用的时候，你必须在页面上引用它们。为此，需要对&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;JavaScriptHelper&lt;/span&gt;类做如下修改：&lt;/code&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web.UI;&lt;br /&gt;&lt;br /&gt;[assembly: WebResource(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JavaScriptLibrary.JavaScript.ShowMessage.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;application/x-javascript&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;[assembly: WebResource(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JavaScriptLibrary.JavaScript.GreetUser.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;application/x-javascript&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt; JavaScriptLibrary&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 帮助页面引用嵌入式JS文件&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; JavaScriptHelper{&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt;&lt;span style="color: #000000;"&gt; 静态字段&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; NAME_SHOW_MESSAGE &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JavaScriptLibrary.JavaScript.ShowMessage.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; NAME_GREET_USER &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JavaScriptLibrary.JavaScript.GreetUser.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt;&lt;span style="color: #000000;"&gt; 公共方法&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 在页面上引用ShowMessage.js文件&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="manager"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;通过Page.ClientScript访问&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Include_ShowMessage(ClientScriptManager manager){&lt;br /&gt;            IncludeJavaScript(manager, NAME_SHOW_MESSAGE);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 在页面上引用GreetUser.js文件 (包括所有依赖文件) &lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="manager"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;通过Page.ClientScript访问&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Include_GreetUser(ClientScriptManager manager){&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;依赖(ShowMessage.js).&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            Include_ShowMessage(manager);&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;引用 GreetUser.js.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            IncludeJavaScript(manager, NAME_GREET_USER);&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt;&lt;span style="color: #000000;"&gt; 私有方法&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 在页面上引用指定的嵌入式js文件&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="manager"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;通过Page.ClientScript访问&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="resourceName"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;用于标示嵌入式JS文件的名字&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; IncludeJavaScript(ClientScriptManager manager, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; resourceName){&lt;br /&gt;            var type &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(JavaScriptLibrary.JavaScriptHelper);&lt;br /&gt;            manager.RegisterClientScriptResource(type, resourceName);&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;IncludeJavaScript()&lt;/span&gt;是关键所在。它通过调用&lt;/code&gt;&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;RegisterClientScriptResource()&lt;/span&gt;确保为嵌入式JS文件获取一个脚本标签。&lt;/code&gt;&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;Include_GreetUser()&lt;/span&gt;调用了&lt;/code&gt;&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;IncludeJavaScript()&lt;/span&gt;，同时也调用了&lt;/code&gt;&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;Include_ShowMessage()&lt;/span&gt;（用于处理依赖关系）。因此，任何页面在引用&lt;/code&gt;&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;GreetUser()&lt;/span&gt;时也将引用&lt;/code&gt;&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;ShowMessage()&lt;/span&gt;。&lt;/code&gt;&lt;/p&gt;&lt;p&gt;现在我们有了可用的类，接下在让我们在Default.aspx页面中试用它。首先在站点&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;ParchmentPurveyor&lt;/span&gt;中添加对&lt;/code&gt;&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;JavaScriptLibrary&lt;/span&gt;的引用：&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011053120585684.png" /&gt;&lt;/p&gt;&lt;p&gt;接下来我们需要修改引用JS页面的后台代码。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web.UI;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt; ParchmentPurveyor&lt;br /&gt;{&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;partial&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; Default : System.Web.UI.Page{&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnPreRender(EventArgs e){&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;.OnPreRender(e);   &lt;br /&gt;            JavaScriptLibrary.JavaScriptHelper.Include_GreetUser(Page.ClientScript);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;最后，还有一件事要做&amp;mdash;&amp;mdash;从页面调用&lt;span style="color: #993300;"&gt;GreetUser()&lt;/span&gt;。为此，我们需要在页面中添加如下JS（我选择把它添加到&amp;lt;head&amp;gt;标签中）：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;head &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;runat&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="server"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Parchment Purveyor&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;&lt;br /&gt;        window.onload &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; () { GreetUser(); };&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;好了，除了还有一些琐碎的事要处理外，我们已基本完成。在处理那些之前，让让我们看一下成果。编译整个解决方案&amp;mdash;〉右键在浏览器中查看Default.aspx页面：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011053121010289.png" /&gt;&lt;/p&gt;&lt;p&gt;右键查看页面源码，你可能看到如下内容（src="/WebResource.axd.."部分有删减）：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;html &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    Parchment Purveyor&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;&lt;br /&gt;        window.onload &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; () { GreetUser(); };&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;form &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;method&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="post"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; action&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Default.aspx"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="form1"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;div &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;class&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="aspNetHidden"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;input &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="hidden"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; name&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="__VIEWSTATE"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="__VIEWSTATE"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="..."&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/WebResource.axd?d=fslk3GLsk3Slek&amp;amp;amp;t=1234"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="/WebResource.axd?d=fglk3kSl3LS5&amp;amp;amp;t=5678"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;h1&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Parchment Purveyor&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;h1&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Paper for printers, painting, publication,&lt;br /&gt;            paper planes, and plenty of other plebeian projects!&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;form&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;请注意引用&amp;ldquo;WebResource.axd&amp;rdquo;的两个&amp;lt;script&amp;gt;标签。它提供了让客户端访问嵌入式信息的基本功能。注意，第一个&amp;lt;script&amp;gt;标签注册了&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;ShowMessage()&lt;/span&gt;,第二个&lt;/code&gt;&amp;lt;script&amp;gt;标签注册了&lt;span style="color: #993300;"&gt;&lt;code lang="text"&gt;GreetUser&lt;/code&gt;&lt;/span&gt;&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;()&lt;/span&gt;。在你的JS库中调用&lt;/code&gt;&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;Include_GreetUser()&lt;/span&gt;时，上面所有标签都会被引入到页面中。&lt;/code&gt;&lt;/p&gt;&lt;h2 id="late_includes"&gt;后期引用&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;有时上面技术可能会引用JS文件失败。例如当我使用第三方工具工作时，就可能在渲染阶段阻止调用.NET代码。当你在渲染阶段引用那些函数时，脚本标签不会被插入页面。这是因为页面一开始就已经呈现为HTML。对这个问题的解决方法是构造一个替换函数,并在HTML底部附近插入脚本标签。我称之为&amp;ldquo;后期引用&amp;rdquo;，为此，需要对&lt;span style="color: #993300;"&gt;JavaScriptHelper&lt;/span&gt;做一些修改：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Web.UI;&lt;br /&gt;&lt;br /&gt;[assembly: WebResource(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JavaScriptLibrary.JavaScript.ShowMessage.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;application/x-javascript&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;[assembly: WebResource(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JavaScriptLibrary.JavaScript.GreetUser.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;application/x-javascript&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt; JavaScriptLibrary {&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 帮助页面引用嵌入式JS文件&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; JavaScriptHelper {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt;&lt;span style="color: #000000;"&gt; Constants&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; TEMPLATE_SCRIPT &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;&amp;lt;script type=\"text/javascript\" src=\"{0}\"&amp;gt;&amp;lt;/script&amp;gt;\r\n&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; NAME_SHOW_MESSAGE &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JavaScriptLibrary.JavaScript.ShowMessage.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; NAME_GREET_USER &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JavaScriptLibrary.JavaScript.GreetUser.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt;&lt;span style="color: #000000;"&gt; 公共方法&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 页面引用ShowMessage.js文件&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="manager"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;通过Page.ClientScript访问&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="late"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;是否在HTML底部引用JS&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Include_ShowMessage(ClientScriptManager manager, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt; late &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {&lt;br /&gt;            IncludeJavaScript(manager, NAME_SHOW_MESSAGE, late);&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 页面引用GreetUser.js文件(包括所有依赖文件)&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="manager"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;通过Page.ClientScript访问&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="late"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;是否在HTML底部引用JS&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Include_GreetUser(ClientScriptManager manager, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt; late &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 依赖 (ShowMessage.js).&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            Include_ShowMessage(manager, late);&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 引用 GreetUser.js.&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            IncludeJavaScript(manager, NAME_GREET_USER, late);&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt;&lt;span style="color: #000000;"&gt; 私有方法&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 页面引用指定的嵌入式JS文件&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="manager"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;通过Page.ClientScript访问&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="resourceName"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;标示嵌入式JS文件的名字&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="late"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;是否在HTML底部引用JS&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; IncludeJavaScript(ClientScriptManager manager, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; resourceName, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt; late) {&lt;br /&gt;            var type &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(JavaScriptLibrary.JavaScriptHelper);&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;manager.IsStartupScriptRegistered(type, resourceName)) {&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (late) {&lt;br /&gt;                    var url &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; manager.GetWebResourceUrl(type, resourceName);&lt;br /&gt;                    var scriptBlock &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Format(TEMPLATE_SCRIPT, HttpUtility.HtmlEncode(url));&lt;br /&gt;                    manager.RegisterStartupScript(type, resourceName, scriptBlock);&lt;br /&gt;                }&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt; {&lt;br /&gt;                    manager.RegisterClientScriptResource(type, resourceName);&lt;br /&gt;                    manager.RegisterStartupScript(type, resourceName, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Empty);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;为每个方法添加一个参数late。该参数默认值为false,因此这些方法依旧可以按照原有方式调用。该参数为false表示原有行为不变，为true时将导致在HTML结尾部分引用脚本段。可能注意到，在late=false时，我仍然调用了&lt;span style="color: #993300;"&gt;RegisterStartupScript()&lt;/span&gt;，但传入了一个空字符串(所以不会在HTML插入任何内容)。完成后&lt;span style="color: #993300;"&gt;IsStartupScriptRegistered()&lt;/span&gt;将会返回正确值。这样，即使在late被置false后调用了其中的一个函数，又把late置为true,JS也不会被多次引用。如果要看效果，注释掉后台代码&lt;span style="color: #993300;"&gt;OnPreRender()&lt;/span&gt;，并在页面中做如下修改：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;form &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="form1"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; runat&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="server"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;h1&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Parchment Purveyor&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;h1&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Paper for printers, painting, publication,&lt;br /&gt;            paper planes, and plenty of other plebeian projects!&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;  &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;//&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; This gets called during the render stage.&lt;br /&gt;            JavaScriptLibrary.JavaScriptHelper.Include_GreetUser(Page.ClientScript, &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;); &lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;form&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在运行程序时，如果观察页面源码，你会发现这将调用HTML底部&amp;lt;script&amp;gt;标签引用的函数。&lt;/p&gt;&lt;h2 id="external_javascript"&gt;外部JS&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;到目前为止，我只是演示了如何引用嵌入式JS。然而，有时候会需要联接到外部JS文件。为此，需要在&lt;span style="color: #993300;"&gt;JavaScriptHelper&lt;/span&gt;添加一个新函数：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #808080;"&gt;        ///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 在页面里引用指定的外部JavaScript文件&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="page"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;当前页面&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="key"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;唯一标示外部JavaScript文件的名字&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="httpUrl"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;外部JavaScript文件的URL地址&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="httpsUrl"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;启用SSL时外部JavaScript文件的URL地址&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="late"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;是否需要在HTML下面引用JavaScript&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; IncludeExternalJavaScript(Page page, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; key, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; httpUrl, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; httpsUrl, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt; late) {&lt;br /&gt;            var manager &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; page.ClientScript;&lt;br /&gt;            var type &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(JavaScriptLibrary.JavaScriptHelper);&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt; isStartupRegistered &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; manager.IsStartupScriptRegistered(type, key);&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt; isScriptRegistered &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; manager.IsClientScriptIncludeRegistered(type, key);&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;(isStartupRegistered &lt;/span&gt;&lt;span style="color: #000000;"&gt;||&lt;/span&gt;&lt;span style="color: #000000;"&gt; isScriptRegistered)) {&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; url;&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (page.Request.Url.Scheme.ToLower() &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;http&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {&lt;br /&gt;                    url &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; httpUrl;&lt;br /&gt;                }&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt; {&lt;br /&gt;                    url &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; httpsUrl;&lt;br /&gt;                }&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (late) {&lt;br /&gt;                    manager.RegisterStartupScript(type, key, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Format(TEMPLATE_SCRIPT, HttpUtility.HtmlEncode(url)));&lt;br /&gt;                }&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt; {&lt;br /&gt;                    manager.RegisterClientScriptInclude(type, key, url);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;做为常用外部JS文件示例，我将使用微软CDN上的JS文件。如其它JS文件一样，首先在&lt;span style="color: #993300;"&gt;JavaScriptHelper &lt;/span&gt;类中添加一个函数，供页面调用jQuery:&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; NAME_JQUERY &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;jQuery&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; URL_JQUERY &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; URL_JQUERY_HTTPS &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 页面引用jQuery.js&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="page"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;当前页面.如果传入为null,则使用HTTP上下文的当前&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="late"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;是否需要在HTML下面引用JavaScript&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Include_jQuery(Page page,&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;bool&lt;/span&gt;&lt;span style="color: #000000;"&gt; late&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;false&lt;/span&gt;&lt;span style="color: #000000;"&gt;) {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (page &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;                page &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; (Page)HttpContext.Current.Handler;&lt;br /&gt;            IncludeExternalJavaScript(page,NAME_JQUERY,URL_JQUERY,URL_JQUERY_HTTPS,late);&lt;br /&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;最后你能后在页面里通过在&lt;span style="color: #993300;"&gt;OnPreRender()&lt;/span&gt;里调用添加的方法实现对jQuery的引用。&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnPreRender(EventArgs e) {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;.OnPreRender(e); &lt;br /&gt;            JavaScriptLibrary.JavaScriptHelper.Include_jQuery(Page);  &lt;br /&gt;            JavaScriptLibrary.JavaScriptHelper.Include_GreetUser(Page.ClientScript);         &lt;br /&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;运行程序，察看页面源码，你会看到如下jQuery引用：&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;h2 id="adding_javascript_files"&gt;添加新的JS文件&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;一旦所有内容完成部署，在需要添加新的JS文件时，只需要几步即可完成，如下：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;在JavaScript目录中添加js文件。引用外部js文件跳过该步骤；&lt;/li&gt;&lt;li&gt;设置&amp;ldquo;生成操作&amp;rdquo;为&amp;ldquo;嵌入资源&amp;rdquo;。引用外部js文件跳过该步骤；&lt;/li&gt;&lt;li&gt;添加assembly属性表示js文件为Web资源。引用外部js文件跳过该步骤；&lt;/li&gt;&lt;li&gt;在&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;JavaScriptHelper&lt;/span&gt;类中添件一个引用JS文件的函数；&lt;/code&gt;&lt;/li&gt;&lt;li&gt;从页面，控件或母版页上调用你创建的函数；&lt;/li&gt;&lt;/ul&gt;&lt;h2 id="excluding_javascript"&gt;不引用JS文件&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;以上所做都是为了引用JS文件，但也有时候你可能不需要引用JS文件。例如，在使用第三方控件库时，它们可能通过其他方式引用了JS，这时唯一阻止某一JS文件被两次引用的方法是通过你的代码消除重复引用（由第三方库帮你引用，不需要重复引用）。这可以通过在&lt;code lang="text"&gt;&lt;span style="color: #993300;"&gt;JavaScriptHelper&lt;/span&gt;增加额外的函数&lt;/code&gt;实现。在实现之前，先让我们演示一下这些技术应用的场景。假设你的第三方控件&lt;span style="color: #993300;"&gt;InlineGreeting.ascx&lt;/span&gt;引用了jQuery，其内容大致如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;@ Control Language&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;C#&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; &lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;--&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; This &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;is&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; a bad way &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;to&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;do&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; things, but we can luckily overcome this obstacle. &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;--&lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; src&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;&lt;br /&gt;    $(document).ready(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;function&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;() {&lt;br /&gt;        $(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;#lblGreeting&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;).text(&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;Hello&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;);&lt;br /&gt;    });&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;label &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="lblGreeting"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;label&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;现在假设我们有另一个自己的控件&lt;span style="color: #993300;"&gt;Hello.ascx&lt;/span&gt;，使用了同样的jQuery文件：&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;@ Control Language&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;C#&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; AutoEventWireup&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;true&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; CodeBehind&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;Hello.ascx.cs&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; Inherits&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;=&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;ParchmentPurveyor.Hello&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #800000;"&gt;"&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; &lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;&lt;br /&gt;    $(document).ready(GreetUser);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span style="color: #993300;"&gt;Hello.ascx&lt;/span&gt;的后台代码引用了jQuery，如下：&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;        protected override void OnPreRender(EventArgs e) {&lt;br /&gt;            base.OnPreRender(e);&lt;br /&gt;            JavaScriptLibrary.JavaScriptHelper.Include_GreetUser(Page.ClientScript);    &lt;br /&gt;            JavaScriptLibrary.JavaScriptHelper.Include_jQuery(Page);        &lt;br /&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;现在，如果在Default.aspx中引用上述用户控件，jQuery将会被引用两次（第三方一次，我们一次）。为避免此类情况发生，我们将在&lt;span style="color: #993300;"&gt;JavaScriptHelper&lt;/span&gt;类中添加两个方法，&lt;span style="color: #993300;"&gt;ExcludeJavaScript()&lt;/span&gt;和&lt;span style="color: #993300;"&gt;Exclude_jQuery()&lt;/span&gt;：&lt;br /&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; NAME_DUMMY_FILE &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;JavaScriptLibrary.JavaScript.DummyFile.js&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 该页面排除jQuery.js&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="manager"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;通过Page.ClientScript访问&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Exclude_jQuery(ClientScriptManager manager) {&lt;br /&gt;            ExcludeJavaScript(manager, NAME_JQUERY);&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; 注册一个虚假的脚本来阻止包含真实的JavaScript&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="manager"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;通过Page.ClientScript访问&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;param name="key"&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;唯一标示JavaScript文件的名字&lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; ExcludeJavaScript(ClientScriptManager manager, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; key) {&lt;br /&gt;            var type &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(JavaScriptLibrary.JavaScriptHelper);&lt;br /&gt;            var url &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; manager.GetWebResourceUrl(type, NAME_DUMMY_FILE);&lt;br /&gt;            manager.RegisterStartupScript(type, key, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Empty);&lt;br /&gt;            manager.RegisterClientScriptInclude(type, key, url);&lt;br /&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;注意,我们定义了一个新的常量&lt;span style="color: #993300;"&gt;NAME_DUMMY_FILE&lt;/span&gt;。上面函数假定我们按照上述步骤在JavaScript文件夹里添加了一个空JS文件，并嵌入了它。这个空虚拟JS文件可以引用在任何我们想不引用JS文件的地方。为阻止我们的库引用jQuery只需要调用在Default.aspx页面的&lt;span style="color: #993300;"&gt;Page_Load()&lt;/span&gt;中调用&lt;span style="color: #993300;"&gt;Exclude_jQuery()&lt;/span&gt;：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Page_Load(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt; sender, EventArgs e) {            &lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;我们通过第三方控件引用了jQuery,那么将避免再一次引用&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            JavaScriptLibrary.JavaScriptHelper.Exclude_jQuery(Page.ClientScript);&lt;br /&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;现在我们要做的是修改Default.aspx引用&lt;span style="color: #993300;"&gt;InlineHello.ascx&lt;/span&gt;和&lt;span style="color: #993300;"&gt;Hello.ascx&lt;/span&gt;，结果如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;...&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;html &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;xmlns&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;head &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;runat&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="server"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Parchment Purveyor&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;title&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;script &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="text/javascript"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;//&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt; window.onload = function () { GreetUser(); };&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;head&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;form &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="form1"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; runat&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="server"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;h1&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Parchment Purveyor&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;h1&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;Paper for printers, painting, publication,&lt;br /&gt;            paper planes, and plenty of other plebeian projects!&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;p&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;  &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;//&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; 这在渲染阶段调用&lt;br /&gt;            JavaScriptLibrary.JavaScriptHelper.Include_GreetUser(Page.ClientScript, &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #0000ff;"&gt;true&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;); &lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;--&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; An inline greeting (pretend this comes from a third&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;-&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;party control library. &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;--&lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;greet:InlineHello &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;ID&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="InlineHello1"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; runat&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="server"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;--&lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt; Our jQuery greeting. &lt;/span&gt;&lt;span style="background-color: #f5f5f5; color: #000000;"&gt;--&lt;/span&gt;&lt;span style="background-color: #ffff00; color: #000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;greet:Hello &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;runat&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="server"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;form&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;body&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;html&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;现在我们已清楚在调用&lt;span style="color: #993300;"&gt;Include_jQuery()&lt;/span&gt;之前先调用&lt;span style="color: #993300;"&gt;Exclude_jQuery()&lt;/span&gt;，就能够阻止我们的JS库引用jQuery.js文件。这就是说jQuery只会被我们的第三方控件引用。大多数时候这种情况可以避免。然而，有时候不可避免，这时该技术也可以让我们的HTML更加干净整洁。&lt;/p&gt;&lt;h2 id="what_did_you_gain"&gt;你都有哪些收获?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;经过这些工作，依旧有同样的HTML输出，你可能会问&amp;ldquo;通过添加这些额外的代码，我获得了什么？&amp;rdquo;。那么这里就列出几点：&lt;/p&gt;&lt;ul&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;内联JS&lt;/strong&gt;：通过避免把JS直接内联到页面,减小了页面尺寸。 &lt;/li&gt;&lt;li&gt;&lt;strong&gt;发布JS&lt;/strong&gt;：当你发布Web站点时，你不需要发布引用的JS文件，只发布DLL就足够了。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;错误引用&lt;/strong&gt;：即使改变了程序路径，你也不用为修改JS路径担忧。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;依赖性&lt;/strong&gt;：文件依赖自动管理。如果你引用了GreetUser.js文件，那么ShowMessage.js文件会自动被引用。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;无效引用&lt;/strong&gt;：除非你调用的函数引用了它，否则不会有JS加载到页面。这将避免页面上出现无用的JS（潜在的加快了页面载入时间）。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;HTTP/HTTPS&lt;/strong&gt;：脚本标记的代码输出与协议无关，因此协议对所有页面一样。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;重构&lt;/strong&gt;：如果你想使用一个不同版本的脚本，你只需要在一个地方修改它。例如，如果你决定切换到CDN版本的jQuery，而不是你自己承载，这可能非常有用。更新一个新版本的jQuery时也非常有用。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;冗余&lt;/strong&gt;：不管你在方法中引用多少次，该脚本标签仅会在页面上本引用一次。&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;/ul&gt;&lt;img src="http://www.cnblogs.com/niyw/aggbug/2064937.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/niyw/archive/2011/06/02/2064937.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/niyw/archive/2011/05/30/2062071.html</id><title type="text">如何向妻子解释设计模式</title><summary type="text">自上篇翻译后收到了很好的反应。故特继续翻译作者的一文，以飨读者。在此文中，作者依旧通过与妻子浅显易懂的对话，向读者解释了什么是设计模式。</summary><published>2011-05-30T01:55:00Z</published><updated>2011-05-30T01:55:00Z</updated><author><name>倪大虾</name><uri>http://www.cnblogs.com/niyw/</uri></author><link rel="alternate" href="http://www.cnblogs.com/niyw/archive/2011/05/30/2062071.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/niyw/archive/2011/05/30/2062071.html"/><content type="html">&lt;p&gt;&lt;strong&gt;简介&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;自上篇翻译&amp;lt;&lt;a href="http://www.cnblogs.com/niyw/archive/2011/01/25/1940603.html"&gt;如何向妻子解释OOD&lt;/a&gt;&amp;gt;后收到了很好的反应。故特继续翻译作者的&amp;lt;&lt;a href="http://www.codeproject.com/KB/architecture/LearningDesignPatterns1.aspx"&gt;How I explained Design Patterns to my wife: Part 1&lt;/a&gt;&amp;gt;一文，以飨读者。在此文中，作者依旧通过与妻子浅显易懂的对话，向读者解释了什么是设计模式。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;设计模式是什么?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:通过我们关于面向对象设计原则（OODP，即SOLID原则）的对话，我想你已经对面向对象设计原则（OODP）有了基本的认识。希望你不要介意我把对话分享到博客上。你可以在这找到它：&lt;a href="http://www.codeproject.com/KB/architecture/SOLIDPrinciplesInOOD.aspx"&gt;&amp;lt;&lt;/a&gt;&lt;a href="http://www.cnblogs.com/niyw/archive/2011/01/25/1940603.html"&gt;如何向妻子解释OOD&lt;/a&gt;&amp;gt;.&lt;/p&gt;&lt;p&gt;设计模式是这些原则在某些特定公共场景下标准化的应用，接下来让我们通过一些例子学习什么是设计模式。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 当然，我喜欢例子。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 让我们以汽车为例讨论一下。汽车是一个很复杂的对象，由成千上万的其它对象组成，如发动机，车轮，方向盘，车座，车体等等其他不同的部分或部件。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011052917421510.png" /&gt;&lt;/p&gt;&lt;div class="Caption"&gt;&lt;em&gt;&lt;span style="font-size: 12px;"&gt;汽车部件&lt;/span&gt;&lt;/em&gt;&lt;/div&gt;&lt;p&gt;当装配汽车时，制造商需要集中并装配这些更小的自成汽车子系统的不同部件。而这些不同的小部件同样也是复杂的对象，其它制造商同样要生产并组装它们。在生产汽车时，汽车公司并不会为怎么生产组装这些部件操心（前提是他们要确保这些对象/设备的质量）。当然，汽车制造商更加关心怎么装配这些不同部件以便能生产不同型号的汽车。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011052917543161.png" /&gt;&lt;/p&gt;&lt;div class="Caption"&gt;&lt;em&gt;&lt;span style="font-size: 12px;"&gt;通过遵循不同的设计，组装不同的部件，生产不同型号的汽车&lt;/span&gt;&lt;/em&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 汽车制造公司必须有如何生产不同型号汽车的设计图或蓝图，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 当然，并且这些设计都是良好的，他们花费大量的时间和精力来做这些设计。一旦设计完成，生产汽车就仅仅是照葫芦画瓢了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 嗯。如果事先有一些好的设计，就能在短时间内遵照这些设计生产不同产品，并且制造商在每次生产某一个型号产品时就不需要重新设计或重新发明车轮，他们只需要按照已有的设计办事就行了。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011052918111049.png" /&gt;&lt;/p&gt;&lt;div class="Caption"&gt;&lt;em&gt;&lt;span style="font-size: 12px;"&gt;生产不同型号产品（汽车）的不同设计图&lt;/span&gt;&lt;/em&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 你抓到重点了。现在假设我们是软件生产商，我们使用基于需求而来的不同组件或功能构建各种不同的软件程序。当生产这些不同软件系统时，我们常常需要为一些不同软件系统中存在的相同情况开发代码，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 是的，在开发不同软件程序时经常遇到相同的设计问题。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 我们尝试使用面向对象的方式开发软件，并尝试应用OOPD来让代码能易于维护，可复用，可扩展。无论什么时候，当我们遇到这些设计问题时，如果我们有一组经过谨慎开发，良好测试的对象以供使用会不会更好呢？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 是的，这样能够节省时间，生产出更好的软件，且利于以后维护。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 很好！从设计上来说，它的好处是你不需要开发那些对象。经过多年发展，人们已经遇到过一些类似的设计问题，并已经形成有一些公认的，良好的已标准化的设计方案。我们称之为设计模式。&lt;/p&gt;&lt;p&gt;我们一定好感谢四人组，他们在《设计模式：可复用面向对象软件设计》中总结出了23种基本的设计模式。四人组由Erich Gamma, Richard Helm, Ralph Johnson, 和John Vlissides组成。实际中有很多面向对象设计模式，但这23种模式被公认为是所有其他设计模式的基础。 &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 我能发明一个新的模式吗？这可能吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 当然，亲爱的，为什么不能呢？！设计模式不是由科学家发明创造的。它们是被发现找到的。这意味着任何通用问题场景中都有一些好的设计方案在那。如果我们能够指出一个能够解决一个新的设计相关问题的面向对象设计，那么这将会是一个由我们定义的新的设计模式。谁知道呢？！如果我们发现找到一些设计模式，或许将来有一天人们会称我们为二人组，哈哈。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Fahana&lt;/strong&gt;: :)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;我们将如何学习设计模式？&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 我一直认为例子是学习的最好途径。在我们的学习方法中，我们不会先讨论理论后讨论实现。我认为这是很糟糕的方式。设计模式不是基于理论的发明。事实上，问题场景首先出现，其次是基于这些问题的来龙去脉和需求，然后是一些设计方案的演化，最后其中的一些被标准化为模式。所以对每一个我们讨论的设计模式，我们将尝试理解并分析一些现实生活中的例子，然后一步步尝试归纳一个设计，并最后总结一些与某些模式匹配设计。设计模式就是在这些相似过程中发现的。你认为呢？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:我想这种方式对我更有用。如果我能通过分析问题和归纳方案得出设计模式，我就不用死记那些设计模式和定义了。请按照你的方式继续。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;一个常见的设计问题和它的解决方案&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 让我们考虑下面的场景：&lt;/p&gt;&lt;p&gt;我们房间里有些电器（电灯，风扇等）。这些设备按照某些方式布局，并由开关控制。任何时候你都能替换或排查一个电器而不用碰到其他东西。例如，你可以换一个电灯而不需要换开关。同样，你可以换一个开关或排查它而不需要碰到或替换相应的电灯或风扇；甚至你可以用把电灯连接到风扇的开关上，把风扇连到电灯的开关上，而不需要碰到开关。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011052920012962.png" /&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&lt;span style="font-size: 12px;"&gt;电器：风扇和电灯&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011052920020560.png" /&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&lt;span style="font-size: 12px;"&gt;风扇和电灯的两种不同开关，一个普通点，另一个别致点&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 是的，但就是这样子，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 是的，确实如此，就该如此布局。当不同东西联系在一起时，它们应该按照一定方式联系：修改或替换一个系统时不会影响到另一个，或者说即便有，也应该最小化。这能够让你的系统易于管理，且成本低。想想一下，如果改一下房间里的灯同时需要改开关，你会乐意在你房子上花钱并安装这个系统吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 当然不会。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 现在，让我们思考一下电灯或风扇如何连接到开关上才能达到改变一个不会影响到另一个。你认为该如何？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 用电线!&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 很好。把电灯/风扇和开关联系到一起的是电线和电器布局。我们可以它们看做不同系统间相互联系的桥梁。其基本的思想是，一个事物不能和另一外一个事物直接联系。当然啦，它们应当通过某些桥梁或接口联系在一起。用软件术语来说，这叫&amp;ldquo;松耦合&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 我知道了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 现在，让我们尝试推断在电灯/风扇和开关例子中的几个关键问题，并尝试推断它们是如何设计并联系起来的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 好，我们试一下。&lt;/p&gt;&lt;p&gt;例子中我们有开关，可能有几种开关，如普通的开关，漂亮的开关，但通常来说它们还是开关，并且每种开关都能够打开和关闭。&lt;/p&gt;&lt;p&gt;所以下面我们会有一个开关基类&lt;span style="color: #993300;"&gt;Switch&lt;/span&gt;：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; Switch {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; On() {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;打开开关&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Off() {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;关闭开关&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        }&lt;br /&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;接下来我们可以有一些具体的开关，例如一个漂亮开关，一个普通开关等等，当然，&lt;code&gt;我们会让类&lt;span style="color: #993300;"&gt;FancySwitch&lt;/span&gt;和&lt;/code&gt;&lt;span style="color: #993300;"&gt;&lt;code&gt;NormalSwitch&lt;/code&gt;nd&lt;/span&gt;继承类&lt;code&gt;&lt;span style="color: #993300;"&gt;Switch&lt;/span&gt;：&lt;/code&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; NormalSwitch : Switch {&lt;br /&gt;    }&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; FancySwitch : Switch {&lt;br /&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;这里的两个具体类有自己的特征和行为，只是此时此刻，我们简单化以下。&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 非常棒，接下来电灯和风扇怎么办？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 我试试. 根据OODP的开放闭合原则，我们知道只要可能，就应该尝试抽象，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 对&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 跟开关不一样，风扇和电灯等是两种不同的事物。对于开关，我们能够使用一个开关基类&lt;span style="color: #993300;"&gt;&lt;code&gt;Switch&lt;/code&gt;&lt;/span&gt;，但风扇和电灯是两个不同的事物，相比定义一个基类，接口可能更合适。一般来说，他们都是电器。所以我们可以定义一个接口，如&lt;code&gt;&lt;span style="color: #993300;"&gt;IElectricalEquipment&lt;/span&gt;，作为对电灯和风扇的抽象，可以吗？&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 可以&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 好，每种电器都有些相同的功能。他们能够打开和关闭。所以接口可能如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;interface&lt;/span&gt;&lt;span style="color: #000000;"&gt; IElectricalEquipment {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; PowerOn(); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;每种电器都能打开&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; PowerOff(); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;每种电器都能关闭&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 太好了，你很善于抽象东西。现在我们需要一座桥梁。在现实中，电线是桥梁。在我们对象设计中，开关知道如何打开和关闭电器，电器以某种方式联系到开关。这里我们没有电线，让电器连接到开关的唯一方式是封装。&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 是的，但开关不能直接知道风扇或电灯。开关应当知道一个电器&lt;code&gt;&lt;span style="color: #993300;"&gt;IElectricalEquipment&lt;/span&gt;能够打开或关闭。这意味着，&lt;/code&gt;&lt;span style="color: #993300;"&gt;&lt;code&gt;ISwitch&lt;/code&gt;&lt;/span&gt;应该有一个&lt;code&gt;&lt;span style="color: #993300;"&gt;IElectricalEquipment&lt;/span&gt;实例，对吗？&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 对，对风扇或电灯的封装的实例是一个桥梁。所以让我们修改&lt;code&gt;&lt;span style="color: #993300;"&gt;Switch&lt;/span&gt;类以便封装一个电器：&lt;/code&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; Switch {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; IElectricalEquipment equipment {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; On() {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;开关打开&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Off() {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;开关关闭&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        }&lt;br /&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 明白。让我们定义真实的电器：风扇和电灯。如我所见，一般来说它们都是电器，所以它们都简单实现了&lt;code&gt;IElectricalEquipment&lt;/code&gt;接口。&lt;p&gt;下面是风扇类:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; Fan : IElectricalEquipment {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; PowerOn() {&lt;br /&gt;            Console.WriteLine(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;风扇打开&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; PowerOff() {&lt;br /&gt;            Console.WriteLine(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;风扇关闭&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;        }&lt;br /&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;下面是电灯类:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; Light : IElectricalEquipment {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; PowerOn() {&lt;br /&gt;            Console.WriteLine(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;电灯打开&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; PowerOff() {&lt;br /&gt;            Console.WriteLine(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;电灯关闭&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;        }&lt;br /&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:太好了。现在让开关工作。当开关打开关闭的时候它应当能够打开关闭电器（它连接到的） 。&lt;/p&gt;&lt;p&gt;这里的关键点是：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;当开关按下开时，连接的电器也应该打开。&lt;/li&gt;&lt;li&gt;当开关按下关时，连接的电器也应该关闭。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;大致的代码如下:&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Main(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[] args) {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;构造电器设备:风扇,开关&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            IElectricalEquipment fan &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Fan();&lt;br /&gt;            IElectricalEquipment light &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Light();&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;构造开关&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            Switch fancySwitch &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; FancySwitch();&lt;br /&gt;            Switch normalSwitch &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; NormalSwitch();&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;把风扇连接到开关&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            fancySwitch.equipment &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; fan;&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;开关连接到电器,那么当开关打开或关闭时电器应该打开/关闭&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            fancySwitch.On();&lt;br /&gt;            fancySwitch.Off();&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;把电灯连接到开关&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            fancySwitch.equipment &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; light;&lt;br /&gt;            fancySwitch.On(); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;打开电灯&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            fancySwitch.Off(); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;关闭电灯&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 明白。开关的On()方法应当内部调用电器的TurnOn()方法，Off()方法应当内部调用TurnOff()方法，所以开关类Switch应如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; Switch {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; IElectricalEquipment equipment {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; On() {&lt;br /&gt;            Console.WriteLine(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;开关打开&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;            equipment.PowerOn();&lt;br /&gt;        }&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Off() {&lt;br /&gt;            Console.WriteLine(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;开关关闭&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;            equipment.PowerOff();&lt;br /&gt;        }&lt;br /&gt;    }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 很好。这自然允许你把风扇从一个开关接到另一个上。不过你看，反过来也可以。这意味着你可以改变风扇或电灯的开关而不需要碰到风扇或电灯。例如，你可以很轻松的把点灯的开关从FancySwitch换到NormalSwitch上，如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;div&gt;&lt;span style="color: #000000;"&gt;            normalSwitch.equipment &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; light;&lt;br /&gt;            normalSwitch.On(); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;打开电灯&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            normalSwitch.Off(); &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt;关闭电灯&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;你看，连接一个抽象电器到一个开关（通过封装）能够让你改变开关和电器而不会对对方产生影响。这个设计是优雅的，良好的。四人组为该模式取名为：桥接模式。&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 太棒了。我想我明白这个了。从根本上说，两个系统不应当直接联系或依赖与对方。 当然，他们应该联系或依赖于抽象（如依赖倒置原则和开放闭合原则所讲），所以他们是松耦合的，因此我们可以在需要时改变我们的实现而不会对系统其他部分产生过多影响。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 你理解了，亲爱的.我们看下桥接模式的定义：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;"&lt;span style="font-family: Verdana;" face="Verdana"&gt;&lt;span style="font-family: Verdana;" face="Verdana"&gt;&lt;span style="font-family: Verdana;" face="Verdana"&gt;将抽象部分与实现部分分离，使它们都可以独立的变化&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;"&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;你看我们的实现完美遵循该定义。如果你有一个类设计器（如Visual Studio或其他支持该功能的IDE环境），你会看到类似的如下类图：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011052921300861.gif" /&gt;&lt;/p&gt;&lt;div class="Caption"&gt;&lt;em&gt;&lt;span style="font-size: 12px;"&gt;桥接模式类图&lt;/span&gt;&lt;/em&gt;&lt;/div&gt;&lt;p&gt;在这里， &lt;strong&gt;Abstraction&lt;/strong&gt; 是&lt;code&gt;开关基类&lt;span style="color: #993300;"&gt;Switch&lt;/span&gt;。&lt;/code&gt; &lt;strong&gt;RefinedAbstraction&lt;/strong&gt; 是具体开关类 (&lt;span style="color: #993300;"&gt;&lt;code&gt;FancySwitch&lt;/code&gt;&lt;/span&gt;, &lt;span style="color: #993300;"&gt;&lt;code&gt;NormalSwitch&lt;/code&gt; &lt;/span&gt;等等。)。 &lt;strong&gt;Implementor&lt;/strong&gt; 是电器接口&lt;span style="color: #993300;"&gt;&lt;code&gt;IElectricalEquipment&lt;/code&gt;&lt;/span&gt;。&lt;strong&gt;ConcreteImplementorA&lt;/strong&gt; &lt;strong&gt;和ConcreteImplementorB&lt;/strong&gt; 是电灯类&lt;span style="color: #993300;"&gt;Light&lt;/span&gt;和风扇类&lt;span style="color: #993300;"&gt;Fan&lt;/span&gt;。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 问你个问题，只是好奇啊。如你所说有很多其他的设计模式，为什么你以桥接模式开始呢？有重要原因吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 这个问题很好。是的，我以桥接模式而不以其他开始是因为一个理由。我认为桥接模式是所有面向对象模式的基础。理由如下：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;它教导如何思考抽象，这是面向对象设计模式的关键概念。&lt;/li&gt;&lt;li&gt;它实现了基本的OOD原则。&lt;/li&gt;&lt;li&gt;它容易理解。&lt;/li&gt;&lt;li&gt;如果正确理解该模式，学习其他模式会很容易。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 你认为我理解的对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 我认为你理解的非常正确。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;: 那么接下来是什么？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;: 通过理解桥接模式，我们仅仅是开始理解设计模式的思想。在我们接下的对话中，我们将会学习其他的设计模式，我希望你不会觉得它们无聊。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:不会的，相信我。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/niyw/aggbug/2062071.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/niyw/archive/2011/05/30/2062071.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/niyw/archive/2011/01/25/1940603.html</id><title type="text">如何向妻子解释OOD</title><summary type="text">此文译自CodeProject上《How I explained OOD to my wife》一文。作者通过简显易懂的对话非常清晰地阐述了面向对象设计(OOD)的5个基本原则,以及与面向对象编程基本原则的区别与联系。</summary><published>2011-01-25T13:47:00Z</published><updated>2011-01-25T13:47:00Z</updated><author><name>倪大虾</name><uri>http://www.cnblogs.com/niyw/</uri></author><link rel="alternate" href="http://www.cnblogs.com/niyw/archive/2011/01/25/1940603.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/niyw/archive/2011/01/25/1940603.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;span style="color: #993300;"&gt;前言&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;此文译自CodeProject上&amp;lt;&lt;a href="http://www.codeproject.com/KB/architecture/SOLIDPrinciplesInOOD.aspx"&gt;How I explained OOD to my wife&lt;/a&gt;&amp;gt;一文，该文章在Top Articles上排名第3，读了之后觉得非常好，就翻译出来，供不想读英文的同学参考学习。&lt;/p&gt;&lt;p&gt;作者(Shubho)的妻子(Farhana)打算重新做一名软件工程师(她本来是，后来因为他们孩子出生放弃了)，于是作者就试图根据自己在软件开发设计方面的经验帮助她学习面向对象设计(OOD)。&lt;/p&gt;&lt;p&gt;自作者从事软件开发开始，作者常常注意到不管技术问题看起来多复杂，如果从现实生活的角度解释并以对答的方式讨论，那么它将变得更简单。现在他们把在OOD方面有些富有成效的对话分享出来，你可能会发现那是一种学习OOD很有意思的方式。&lt;/p&gt;&lt;p&gt;下面就是他们的对话：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color: #993300;"&gt;OOD简介&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:亲爱的，让我们开始学习OOD吧。你了解面向对象原则吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:你是说封装，继承，多态对吗？我知道的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:好，我希望你已了解如何使用类和对象。今天我们学习OOD。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:等一下。面向对象原则对面向对象编程(OOP)来说不够吗？我的意思是我会定义类，并封装属性和方法。我也能根据类的关系定义它们之间的层次。如果是，那么还有什么？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:问得好。面向对象原则和OOD实际上是两个不同的方面。让我给你举个实际生活中的例子帮你弄明白。&lt;/p&gt;&lt;p&gt;&amp;nbsp;再你小时候你首先学会字母表，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:嗯&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:好。你也学了单词，并学会如何根据字母表造词。后来你学会了一些造句的语法。例如时态，介词，连词和其他一些让你能造出语法正确的句子。例如：&lt;/p&gt;&lt;p&gt;&lt;span style="background-color: #ffcc99;"&gt;"I" (代词) "want" (动词) "to" (介词) "learn" (动词) "OOD"(名词)。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;看，你按照某些规则组合了单词，并且你选择了有某些意义的正确的单词结束了句子。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:OK，这意味着什么呢？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:面向对象原则与这类似。OOP指的是面向对象编程的基本原则和核心思路。在这里，OOP可以比作英语基础语法，这些语法教你如何用单词构造有意义且正确的句子，OOP教你在代 码中构造类，并在类里封装属性和方法，同时构造他们之间的层次关系。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:嗯..我有点感觉了，这里有OOD吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:马上就有答案。现在假定你需要就某些主题写几篇文章或随笔。你也希望就几个你擅长主体写几本书。对写好文章/随笔或书来说，知道如何造句是不够的，对吗？为了使读者能更轻 &amp;nbsp; 松的明白你讲的内容，你需要写更多的内容，学习以更好的方式解释它。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:看起来有点意思...继续。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:现在，如果你想就某个主题写一本书，如学习OOD，你知道如何把一个主题分为几个子主题。你需要为这些题目写几章内容，也需要在这些章节中写前言，简介，例子和其他段落。 &amp;nbsp; 你需要为写个整体框架，并学习一些很好的写作技巧以便读者能更容易明白你要说的内容。这就是整体规划。&lt;/p&gt;&lt;p&gt;在软件开发中，OOD是整体思路。在某种程度上，设计软件时，你的类和代码需能达到模块化，可复用，且灵活，这些很不错的指导原则不用你重新发明创造。确实有些原则你已经在你的类和对象中已经用到了，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:嗯...有个大概的印象了，但需要继续深入。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:别担心，你马上就会学到。我们继续讨论下去。&lt;/p&gt;&lt;h2 style="margin-top: 5px; margin-right: auto; margin-bottom: 5px; margin-left: auto; text-indent: 0px;"&gt;&lt;span style="color: #993300;"&gt;为什么要OOD？&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:这是一个非常重要的问题。当我们能很快地设计一些类，完成开发并发布时，为什么我们需要关心OOD？那样子还不够吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:嗯，我早先并不知道OOD，我一直就是开发并发布项目。那么关键是什么？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:好的，我先给你一句名言：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;走在结冰的河边不会湿鞋，开发需求不变的项目畅通无阻(&lt;span style="font-family: Verdana, Arial, sans-serif; line-height: 16px; font-size: 13px;"&gt;Walking on water and developing software from a specification are easy if both are frozen&lt;/span&gt;)&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: Verdana, Arial, sans-serif; line-height: 16px; font-size: 13px;"&gt;-&lt;em&gt;&lt;span style="color: #004cd5;" color="#004CD5"&gt;Edward V.&lt;/span&gt;&amp;nbsp;&lt;span style="color: #004cd5;" color="#004CD5"&gt;Berard&lt;/span&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:你的意思是软件开发说明书会不断变化？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:非常正确！软件开发唯一的真理是&amp;ldquo;软件一定会变化&amp;rdquo;。为什么?&lt;/p&gt;&lt;p&gt;因为你的软件解决的是现实生活中的业务问题，而现实生活中得业务流程总是在不停的变化。&lt;/p&gt;&lt;p&gt;假设你的软件在今天工作的很好。但它能灵活的支持&amp;ldquo;变化&amp;rdquo;吗？如果不能，那么你就没有一个设计敏捷的软件。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:好，那么请解释一下&amp;ldquo;设计敏捷的软件&amp;rdquo;。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:"一个设计敏捷的软件能轻松应对变化，能被扩展，并且能被复用。"&lt;/p&gt;&lt;p&gt;并且应用好"面向对象设计"是做到敏捷设计的关键。那么，你什么时候能说你在代码中很好的应用了OOD？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:这正是我的问题。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:如果你代码能做到以下几点，那么你就正在OOD：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;面向对象&lt;/li&gt;&lt;li&gt;复用&lt;/li&gt;&lt;li&gt;能以最小的代价满足变化&lt;/li&gt;&lt;li&gt;不用改变现有代码满足扩展&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;：还有？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:我们并不是孤立的。很多人在这个问题上思考了很多，也花费了很大努力，他们试图做好OOD，并为OOD指出几条基本的原则(那些灵感你能用之于你的OOD)。他们最终也确实总结出了一些通用的设计模式(基于基本的原则)。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:你能说几个吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:当然。这里有很多涉及原则，但最基本的是叫做SOLID的5原则(感谢Uncle Bob,伟大OOD导师)。&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: Verdana, Arial, sans-serif; font-size: 13px; line-height: 16px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;span style="background-color: #ffcc99;"&gt;S = 单一职责原则 Single Responsibility Principle&lt;br/&gt;O = 开放闭合原则 Opened Closed Principle &lt;br/&gt;L = Liscov替换原则 Liscov Substitution Principle&lt;br/&gt;I = 接口隔离原则 Interface Segregation Principle&lt;br/&gt;D = 依赖倒置原则 Dependency Inversion Principle&lt;/span&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;接下去，我们会仔细探讨每一个原则。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color: #993300;"&gt;单一职责原则&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:我先给你展示一张海报。我们应当谢谢做这张海报的人，它非常有意思。&lt;/p&gt;&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://pic002.cnblogs.com/images/2011/141116/2011012320313747.jpg" /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;span style="font-size: 12px;"&gt;单一职责原则海报&lt;/span&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;它说："并不是因为你能，你就应该做"。为什么？因为长远来看它会带来很多管理问题。&lt;/p&gt;&lt;p&gt;从面向对象角度解释为："&lt;strong&gt;引起类变化的因素永远不要多于一个。&lt;/strong&gt;"&lt;/p&gt;&lt;p&gt;或者说"一个类有且只有一个职责"。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;：能解释一下吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:当然，这个原则是说，如果你的类有多于一个原因会导致它变化(或者多于一个职责)，你需要一句它们的职责把这个类拆分为多个类。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:嗯...这是不是意味着在一个类里不能有多个方法？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:不。你当然可以在一个类中包含多个方法。问题是，他们都是为了一个目的。如今为什么拆分是重要的？&lt;/p&gt;&lt;p&gt;那是因为：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;每个职责是轴向变化的；&lt;/li&gt;&lt;li&gt;如果类包含多个职责，代码会变得耦合；&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:能给我一个例子吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:当然，看一下下面的类层次。当然这个例子是从Uncle Bob那里得来，再谢谢他。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012320510748.png" /&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;span style="font-size: 12px;"&gt;违反单一职责原则的类结构图&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;这里，&lt;span style="color: #993300;"&gt;Rectangle&lt;/span&gt;类做了下面两件事：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;计算矩形面积；&lt;/li&gt;&lt;li&gt;在界面上绘制矩形；&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;并且，有两个应用使用了&lt;span style="color: #993300;"&gt;Rectangle&lt;/span&gt;类：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;计算几何应用程序用这个类计算面积；&lt;/li&gt;&lt;li&gt;图形程序用这个类在界面上绘制矩形；&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这违反了SRP(单一职责原则);&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:如何违反的？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:你看，Rectangle类做了两件事。在一个方法里它计算了面积，在另外一个方法了它返回一个表示矩形的GUI。这会带来一些有趣的问题：&lt;/p&gt;&lt;p&gt;在计算几何应用程序中我们必须包含GUI。也就是在开发几何应用时，我们必须引用GUI库；&lt;/p&gt;&lt;p&gt;图形应用中Rectangle类的变化可能导致计算几何应用变化，编译和测试，反之亦然；&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:有点意思。那么我猜我们应该依据职责拆分这个类，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:非常对，你猜我们应该做些什么？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:当然，我试试。下面是我们可能要做的：&lt;/p&gt;&lt;p&gt;拆分职责到两个不同的类中，如：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="color: #993300;"&gt;Rectangle&lt;/span&gt;:这个类应该定义&lt;span style="color: #993300;"&gt;Area()&lt;/span&gt;方法；&lt;/li&gt;&lt;li&gt;&lt;span style="color: #993300;"&gt;RectangleUI&lt;/span&gt;:这个类应继承&lt;span style="color: #993300;"&gt;Rectangle&lt;/span&gt;类，并定义&lt;span style="color: #993300;"&gt;Draw()&lt;/span&gt;方法。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:非常好。在这里，&lt;span style="color: #993300;"&gt;Rectangle&lt;/span&gt;类被计算几何应用使用，而&lt;span style="color: #993300;"&gt;RectangleUI&lt;/span&gt;被图形应用使用。我们甚至可以分离这些类到两个独立的DLL中，那会允许我们在变化时不需要关心另一个就可以实现它。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:谢谢，我想我明白SRP了。SRP看起来是把事物分离成分子部分，以便于能被复用和集中管理。我们也不能把SRP用到方法级别吗？我的意思是，我们可以写一些方法，它们包含做很多事的代码。这些方法可能违反SRP，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:你理解了。你应当分解你的方法，让每个方法只做某一项工作。那样允许你复用方法，并且一旦出现变化，你能购以修改最少的代码满足变化。&lt;/p&gt;&lt;p&gt;&lt;span style="line-height: 31px; font-size: 21px; color: #993300; font-weight: bold;"&gt;开放闭合原则&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:这里是开放闭合原则的海报&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012421035566.jpg" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;em&gt;&lt;strong&gt;开放闭合原则海报&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;从面向对象设计角度看,它可以这么说:"&lt;strong&gt;软件实体(类,模块,函数等等)应当对扩展开放，对修改闭合。&lt;/strong&gt;"&lt;/p&gt;&lt;p&gt;通俗来讲，它意味着你应当能在不修改类的前提下扩展一个类的行为。就好像我不需要改变我的身体而可以穿上衣服。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:有趣。你能够按照你意愿穿上不同的衣服来改变面貌，而从不用改造身体。你对扩展开放了，对不？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:是的。在OOD里，对扩展开发意味着类或模块的行为能够改变，在需求变化时我们能以新的，不同的方式让模块改变，或者在新的应用中满足需求。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:并且你的身体对修改是闭合的。我喜欢这个例子。当需要变化时，核心类或模块的源代码不应当改动。你能用些例子解释一下吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:当然，看下面这个例子。它不支持"开放闭合"原则。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012421165398.png" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;em&gt;&lt;strong&gt;违反开发闭合原则的类结构&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;你看，客户端和服务段都耦合在一起。那么，只要出现任何变化，服务端变化了，客户端一样需要改变。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:理解。如果一个浏览器以紧耦合的方式按照指定的服务器(比如IIS)实现，那么如果服务器因为某些原因被其他服务器(如Apache)替换了，那么浏览器也需要修改或替换。这确实很可怕！&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:对的。下面是正确的设计。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012421214012.png" /&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;span style="font-size: 12px;"&gt;遵循开放闭合原则的类结构&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;在这个例子中，添加了一个抽象的服务器类，客户端包含一个抽象类的引用，具体的服务类实现了抽象服务类。那么，因任何原因引起服务实现发生变化时，客户端都不需要任何改变。&lt;/p&gt;&lt;p&gt;这里抽象服务类对修改是闭合的，实体类的实现对扩展是开放的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:我明白了，抽象是关键，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:是的，基本上，你抽象的东西是你系统的核心内容，如果你抽象的好，很可能在扩展功能时它不需要任何修改(就像服务是一个抽象概念)。如果在实现里定义了抽象的东西(比如IIS服务器实现的服务)，代码要尽可能以抽象(服务)为依据。这会允许你扩展抽象事物，定义一个新的实现(如Apache服务器)而不需要修改任何客户端代码。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color: #993300;"&gt;Liskov's 替换原则&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:"Liskov's替换原则(LSP)"听起来很难，却是很有用的基本概念。看下这幅有趣的海报：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012422035591.jpg" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12px;"&gt;&lt;em&gt;&lt;strong&gt;Liskov替换原则海报&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;这个原则意思是："&lt;strong&gt;子类型必须能够替换它们基类型。&lt;/strong&gt;"&lt;/p&gt;&lt;p&gt;或者换个说法："&lt;strong&gt;使用基类引用的函数必须能使用继承类的对象而不必知道它。&lt;/strong&gt;"&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:不好意思，听起来有点困惑。我认为这个OOP的基本原则之一。也就是多态，对吗？为什么一个面向对象原则需要这么说呢？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:问的好。这就是你的答案：&lt;/p&gt;&lt;p&gt;在基本的面向对象原则里，"继承"通常是"&lt;strong&gt;is a&lt;/strong&gt;"的关系。如果"&lt;span style="color: #993300;"&gt;Developer&lt;/span&gt;" 是一个"&lt;span style="color: #993300;"&gt;SoftwareProfessional&lt;/span&gt;",那么"&lt;span style="color: #993300;"&gt;Developer&lt;/span&gt;"类应当继承"&lt;span style="color: #993300;"&gt;SoftwareProfessional&lt;/span&gt;"类。在类设计中"&lt;strong&gt;Is a&lt;/strong&gt;"关系非常重要，但它容易冲昏头脑，结果使用错误的继承造成错误设计。&lt;/p&gt;&lt;p&gt;"&lt;strong&gt;Liskov替换原则&lt;/strong&gt;"正是保证继承能够被正确使用的方法。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:我明白了。有意思。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:是的，亲爱的，确实。我们看个例子：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012422243670.png" /&gt;&lt;/p&gt;&lt;p&gt;Liskov替换原则类结构图&lt;/p&gt;&lt;p&gt;这里，&lt;span style="color: #993300;"&gt;KingFisher&lt;/span&gt;类扩展了&lt;span style="color: #993300;"&gt;Bird&lt;/span&gt;基类，并继承了&lt;span style="color: #993300;"&gt;Fly()&lt;/span&gt;方法，这看起来没问题。&lt;/p&gt;&lt;p&gt;现在看下面的例子：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012422262916.png" /&gt;&lt;/p&gt;&lt;p&gt;违反Liskov替换原则类结构图&lt;/p&gt;&lt;p&gt;&lt;span style="color: #993300;"&gt;Ostrich&lt;/span&gt;(鸵鸟)是一种鸟(显然是),并从&lt;span style="color: #993300;"&gt;Bird&lt;/span&gt;类继承。它能飞吗？不能，这个设计就违反了LSP。&lt;/p&gt;&lt;p&gt;所以，即使在现实中看起来没问题，在类设计中，&lt;span style="color: #993300;"&gt;Ostrich&lt;/span&gt;不应该从&lt;span style="color: #993300;"&gt;Bird&lt;/span&gt;类继承，这里应该从&lt;span style="color: #993300;"&gt;Bird&lt;/span&gt;中分离一个不会飞的类，&lt;span style="color: #993300;"&gt;Ostrich&lt;/span&gt;应该继承与它。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:好，明白了。那么让我来试着指出为什么LSP这么重要：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;如果没有LSP，类继承就会混乱；如果子类作为一个参数传递给方法，将会出现未知行为；&lt;/li&gt;&lt;li&gt;如果没有LSP，适用与基类的单元测试将不能成功用于测试子类；&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:非常正确。你能设计对象，使用LSP做为一个检查工作来测试继承是否正确。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color: #993300;"&gt;接口分离原则&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:今天我们学习"接口分离原则",这是海报：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012422395077.jpg" /&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;span style="font-size: 12px;"&gt;接口分离原则海报&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:这是什么意思？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:它的意思是："客户端不应该被迫依赖于它们不用的接口。"&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:请解释一下。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:当然，这是解释：&lt;/p&gt;&lt;p&gt;假设你想买个电视机，你有两个选择。一个有很多开关和按钮，它们看起来很混乱，且好像对你来说没必要。另一个只有几个开关和按钮，它们很友好，且适合你使用。假定两个电视机提供同样的功能，你会选哪一个？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:当然是只有几个开关和按钮的第二个。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:对，但为什么？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:因为我不需要那些看起来混乱又对我没用的开关和按钮。&lt;/p&gt;&lt;p&gt;&lt;span style="font-family: arial, sans-serif; line-height: normal; font-size: 13px; border-collapse: collapse;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px;"&gt;&lt;strong&gt;Shubho&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-size: 14px;"&gt;:以便外部能够知道这些类有哪些可用的功能,客户端代码也能根据接口来设计.现在,如果接口太大,包含很多暴露的方法,在外界看来会很混乱.接口包含太多的方法也使其可用性降低,像这种包含了无用方法的"胖接口"会增加类之间的耦合.&lt;/span&gt;你通过接口暴露类的功能,对.同样地,假设你有一些类,&lt;/p&gt;&lt;p&gt;这也引起了其他问题.如果一个类想实现该接口,&lt;wbr&gt;&lt;/wbr&gt;那么它需要实现所有的方法,尽管有些对它来说可能完全没用.&lt;wbr&gt;&lt;/wbr&gt;所以说这么做会在系统中引入不必要的复杂度,&lt;wbr&gt;&lt;/wbr&gt;降低可维护性或鲁棒性.&lt;/p&gt;&lt;p&gt;接口隔离原则确保实现的接口有他们共同的职责,它们是明确的,&lt;wbr&gt;&lt;/wbr&gt;易理解的,可复用的.&lt;/p&gt;&lt;div&gt;&lt;span style="font-size: 14px;"&gt;&lt;strong&gt;Farhana&lt;/strong&gt;&lt;/span&gt;&lt;span style="font-family: 宋体; font-size: 14px;"&gt;:&lt;/span&gt;你的意思是接口应该仅包含必要的方法,而不该包含其它的.&lt;span style="font-family: 宋体;"&gt;我明白了.&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:非常正确.一起看个例子.&lt;/p&gt;&lt;div&gt;下面是违反接口隔离原则的一个胖接口&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 宋体; font-size: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012521235320.png" /&gt;&lt;/p&gt;&lt;div&gt;&lt;span style="font-family: 宋体; font-size: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;注意到&lt;span style="color: #993300;"&gt;IBird&lt;/span&gt;接口包含很多鸟类的行为,包括&lt;span style="color: #993300;"&gt;Fly()&lt;/span&gt;行为.&lt;wbr&gt;&lt;/wbr&gt;现在如果一个&lt;span style="color: #993300;"&gt;Bird&lt;/span&gt;类(如Ostrich)实现了这个接口，&lt;wbr&gt;&lt;/wbr&gt;那么它需要实现不必要的&lt;span style="color: #993300;"&gt;Fly()&lt;/span&gt;行为(Ostrich不会飞)&lt;wbr&gt;&lt;/wbr&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:确实如此。那么这个接口必须拆分了？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:是的。这个"胖接口"应该拆分未两个不同的接口，&lt;wbr&gt;&lt;/wbr&gt;&lt;span style="color: #993300;"&gt;IBird&lt;/span&gt;和&lt;span style="color: #993300;"&gt;IFlyingBird&lt;/span&gt;,&lt;wbr&gt;&lt;/wbr&gt;&lt;span style="color: #993300;"&gt;IFlyingBird&lt;/span&gt;继承自&lt;span style="color: #993300;"&gt;IBird&lt;/span&gt;.&lt;/p&gt;&lt;div&gt;&lt;span style="font-family: 宋体; font-size: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012521240226.png" /&gt;&lt;/p&gt;&lt;div&gt;&lt;span style="font-family: 宋体; font-size: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;这里如果一种鸟不会飞(如Ostrich)，&lt;wbr&gt;&lt;/wbr&gt;那它实现&lt;span style="color: #993300;"&gt;IBird&lt;span style="color: #000000;"&gt;接口&lt;/span&gt;&lt;/span&gt;。如果一种鸟会飞(&lt;wbr&gt;&lt;/wbr&gt;如KingFisher)，那么它实现&lt;span style="color: #993300;"&gt;IFlyingBird&lt;/span&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:&lt;wbr&gt;&lt;/wbr&gt;所以回头看包含了很多开关和按钮的电视机的例子，&lt;wbr&gt;&lt;/wbr&gt;电视机制造商应该有一个电视机的图纸，&lt;wbr&gt;&lt;/wbr&gt;开关和按钮都在这个方案里。不论任何时候，&lt;wbr&gt;&lt;/wbr&gt;当他们向制造一种新款电视机时，如果他们想复用这个图纸，&lt;wbr&gt;&lt;/wbr&gt;他们将需要在这个方案里添加更多的开关和按钮。&lt;wbr&gt;&lt;/wbr&gt;那么他们将没法复用这个方案，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:对的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:如果他们确实需要复用方案，&lt;wbr&gt;&lt;/wbr&gt;它们应当把电视机的图纸份为更小部分，&lt;wbr&gt;&lt;/wbr&gt;以便在任何需要造新款电视机的时候复用这点小部分。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:你理解了。&lt;/p&gt;&lt;div&gt;&lt;span&gt;&lt;p&gt;&lt;strong&gt;&lt;span style="color: #993300;"&gt;依赖倒置原则&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:这是SOLID原则里最后一个原则。这是海报&lt;/p&gt;&lt;div&gt;&lt;span style="font-family: 宋体; font-size: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012521244331.jpg" /&gt;&lt;div&gt;&lt;span style="font-family: 宋体; font-size: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;它的意思是：&lt;strong&gt;&lt;span style="text-transform: none; text-indent: 0px; border-collapse: separate; font: normal normal normal medium/normal Simsun; white-space: normal; letter-spacing: normal; color: #000000; word-spacing: 0px;"&gt;&lt;span style="text-align: left; line-height: 18px; color: #666666;"&gt;&lt;span color="#000000" size="3" face="宋体" style="color: #000000; font-size: small;"&gt;高层模块不应该依赖底层模块，两者都应该依赖其抽象&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:考虑一个现实中的例子。你的汽车是由很多如引擎，&lt;wbr&gt;&lt;/wbr&gt;车轮，空调和其它等部件组成，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:是的&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:好，它们没有一个是严格的构建在一个单一单元里；&lt;wbr&gt;&lt;/wbr&gt;换句话说，它们都是可插拔的，因此当引擎或车轮出问题时，&lt;wbr&gt;&lt;/wbr&gt;你可以修理它(而不需要修理其它部件),甚至可以换一个。&lt;/p&gt;&lt;p&gt;在替换时，你仅需要确保引擎或车轮符合汽车的设计(&lt;wbr&gt;&lt;/wbr&gt;如汽车能使用任何1500CC的引擎或任何18寸的车轮)。&lt;/p&gt;&lt;p&gt;当然，&lt;wbr&gt;&lt;/wbr&gt;汽车也可能允许你在1500CC引擎的地方安装一个2000CC&lt;wbr&gt;&lt;/wbr&gt;的引擎，事实上对某些制造商(如丰田汽车)是一样的。&lt;/p&gt;&lt;p&gt;现在，如果你的汽车的零部件不具备可插拔性会有什么不同？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:那会很可怕！因为如果汽车的引擎出故障了，&lt;wbr&gt;&lt;/wbr&gt;你可能修理整部车或者需要买一个新的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:是的，那么该如何做到"可插拔性"呢？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:这里抽象是关键，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:是的，在现实中，汽车是高级模块或实体，&lt;wbr&gt;&lt;/wbr&gt;它依赖于低级模块或实体，如引擎或车轮。&lt;/p&gt;&lt;p&gt;相比直接依赖于引擎或车轮，&lt;wbr&gt;&lt;/wbr&gt;汽车应依赖于某些抽象的有规格的引擎或车轮，&lt;wbr&gt;&lt;/wbr&gt;以便于如果任何引擎或车轮符合抽象，那么它们都能组合到汽车中，&lt;wbr&gt;&lt;/wbr&gt;汽车也能跑动。&lt;/p&gt;&lt;p&gt;一起看下面的类图&lt;/p&gt;&lt;div&gt;&lt;span style="font-family: 宋体; font-size: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/141116/2011012521245287.png" /&gt;&lt;div&gt;&lt;span style="font-family: 宋体; font-size: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:注意到上面&lt;span style="color: #993300;"&gt;Car&lt;/span&gt;类有两个属性，&lt;wbr&gt;&lt;/wbr&gt;它们都是抽象类型(接口)。引擎和车轮是可插拔的，&lt;wbr&gt;&lt;/wbr&gt;因为汽车能接受任何实现了声明接口的对象，&lt;wbr&gt;&lt;/wbr&gt;并且&lt;span style="color: #993300;"&gt;Car&lt;/span&gt;类不需要做任何改动。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:所以，如果代码中不用依赖倒置，&lt;wbr&gt;&lt;/wbr&gt;我们将面临如下风险：&lt;/p&gt;&lt;ul&gt;&lt;li style="margin-left: 15px;"&gt;&lt;p&gt;使用低级类会破环高级代码；&lt;/p&gt;&lt;/li&gt;&lt;li style="margin-left: 15px;"&gt;&lt;p&gt;当低级类变化时需要很多时间和代价来修改高级代码；&lt;/p&gt;&lt;/li&gt;&lt;li style="margin-left: 15px;"&gt;&lt;p&gt;产生低复用的代码；&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:你完全掌握了，亲爱的！&lt;/p&gt;&lt;div&gt;&lt;span style="color: #993300;"&gt;&lt;span style="font-family: 宋体; font-size: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="line-height: 31px; font-size: 21px; font-weight: bold;"&gt;总结&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;：除SOLID原则外还有很多其它的面向对象原则。&lt;wbr&gt;&lt;/wbr&gt;如：&lt;/p&gt;&lt;p&gt;"组合替代继承":这是说相对于继承，要更倾向于使用组合；&lt;/p&gt;&lt;p&gt;"笛米特法则"：这是说"你的类对其它类知道的越少越好"；&lt;/p&gt;&lt;p&gt;"共同封闭原则"：这是说"相关类应该打包在一起"；&lt;/p&gt;&lt;p&gt;"稳定抽象原则"：这是说"类越稳定，越应该由抽象类组成";&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:我应该学习那些原则吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:当然可以。你可以从整个网上学习。&lt;wbr&gt;&lt;/wbr&gt;仅仅需要Google一下那些原则，然后尝试理解它。&lt;wbr&gt;&lt;/wbr&gt;当然如果有需要，尽管问我。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:在那些设计原则之上我听说过很多设计模式。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:对的。&lt;wbr&gt;&lt;/wbr&gt;设计模式只是对一些经常出现的场景的一些通用设计建议。&lt;wbr&gt;&lt;/wbr&gt;这些灵感主要来自于面向对象原则。你可以把设计模式看作"框架"&lt;wbr&gt;&lt;/wbr&gt;,把OOD原则看作"规范".&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:那么接下去我将学习设计模式吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:是的，亲爱的。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Farhana&lt;/strong&gt;:那会很有意思，对吗？&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shubho&lt;/strong&gt;:是，那确实令人兴奋。&lt;/p&gt;&lt;p&gt;-------------------------------------------------------------------------------------------------------------------&lt;/p&gt;&lt;p&gt;&lt;span style="color: #808080; font-family: 楷体;"&gt;&lt;strong&gt;声明:&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="color: #808080; font-family: 楷体;"&gt;&lt;em&gt;&lt;strong&gt;本文版权归作者共有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文出处，连接，作者，否则保留追究法律责任的权利。&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/niyw/aggbug/1940603.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/niyw/archive/2011/01/25/1940603.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/niyw/archive/2010/11/03/1863903.html</id><title type="text">我的工作习惯小结</title><summary type="text">最近有人向我询问如何学习，工作的问题，思前想后，觉得习惯最重要，于是就想到整理一下自己的学习工作习惯。本人工作比较随便，谈不上章法，就随便列举一些。1，正常的作息时间2，工作便条3，日志4，使用好办公软件5，强大小工具：计算器，画图，记事本...6，帮助别人，向他人学习7，贪多嚼不烂8，总结1，正常的作息时间个人觉得这点最重要，所以就放在了第一项。也许是年龄增大的缘故，现在根本熬夜不得。现在每...</summary><published>2010-11-03T00:42:00Z</published><updated>2010-11-03T00:42:00Z</updated><author><name>倪大虾</name><uri>http://www.cnblogs.com/niyw/</uri></author><link rel="alternate" href="http://www.cnblogs.com/niyw/archive/2010/11/03/1863903.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/niyw/archive/2010/11/03/1863903.html"/><content type="html">&lt;p&gt;最近有人向我询问如何学习，工作的问题，思前想后，觉得习惯最重要，于是就想到整理一下自己的学习工作习惯。本人工作比较随便，谈不上章法，就随便列举一些。&lt;/p&gt;&lt;li&gt;&lt;p&gt;&lt;a href="#P1_Label"&gt;1，正常的作息时间&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href="#P2_Label"&gt;2，工作便条&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href="#P3_Label"&gt;3，日志&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href="#P4_Label"&gt;4，使用好办公软件&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a href="#P5_Label"&gt;5，强大小工具：计算器，画图，记事本...&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li style="padding-left: 30px;"&gt;&lt;a href="#P6_Label"&gt;6，帮助别人，向他人学习&lt;/a&gt;&lt;/li&gt;&lt;li style="padding-left: 30px;"&gt;&lt;a href="#P7_Label"&gt;7，贪多嚼不烂&lt;/a&gt;&lt;/li&gt;&lt;li style="padding-left: 30px;"&gt;&lt;a href="#P8_Label"&gt;8，总结&lt;/a&gt;&lt;/li&gt;&lt;p&gt;&lt;a id="P1_Label"&gt;&lt;/a&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;strong&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;1，正常的作息时间&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;个人觉得这点最重要，所以就放在了第一项。也许是年龄增大的缘故，现在根本熬夜不得。现在每天光顾博客园，发现有些人很晚的时候还在发贴，回帖，仿佛不知疲倦。在此衷心劝告一句：莫要透支身体！养成良好的作息规律是人生一大事，毕竟身体健康最重要，其他诸如事业，名利都是浮云！不是说人生最大的悲剧不是没钱花，而是有钱没命花么？！&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;本人现在每天晚上10：00(以往12：00)左右休息，早上7：30(以往8：30)起床，加班之事少有。&lt;/span&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;strong&gt;&lt;a id="P2_Label"&gt;&lt;/a&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;2，工作便条&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;在公司总是事情很多，大事小事每天有十几件很正常，可惜记性不太好，如果不记下来，总会忘这忘那。所以除非遇到的是马上要处理的事，否则必然记下来，方式随便：碎纸片，记事本，札记等等，但要放在显眼的地方。&lt;/span&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;strong&gt;&lt;a id="P3_Label"&gt;&lt;/a&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;3，日志&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;学习的方法很多，其中最好的方法之一莫过于带着问题去学习，但问题解决了要记得把他记下来。初学者，或者比较笨拙的人(比如我自己)尤其应该这么做，目的是为了温故而知新。这样子可以在以后有时间的时候拿出来翻翻，由于是自己不会的东西，所以看起来很快；也正因为是自己不会的东西，看过之后就避免在犯同样的错误或问同样的问题。个人能力也正是在这点滴见积累起来的。个人在工作的时候，尤其是项目发布初期，总是会在一个地方记下该项目自发布运行时期遇到的所有问题，一则避免再犯，二则可以完善思路。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;很多新人刚开始总是问很多问题，有时候没人搭理自己就会觉得很委屈，其实是自己懒，经常问同样的问题才让人烦，所以要谨记这点。好记性不如赖笔头正是如此。&lt;/span&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;strong&gt;&lt;a id="P4_Label"&gt;&lt;/a&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;4，使用好办公软件&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;上面说了几项，总结为一句话就是要记东西，这里就以此举例&amp;mdash;&amp;mdash;使用好OutLook。个人觉得工作中有OutLook就足够了，完全用不着别的软件。OutLook提供了邮件，便条，任务，日历等多种功能，即实用又方便，何乐而不为呢？！本人目前OutLook里邮件自动分了N类，任务列表天天有亮有灰，每天早上上班，从来不用为今天干嘛而发愁，因为9：30有自动提醒。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;当然，如果你用别的办公软件也行，总之公司有的要用起来，没有的就弄个D版的用起来。&lt;/span&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;strong&gt;&lt;a id="P5_Label"&gt;&lt;/a&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;5，强大的小工具：计算器，画图，记事本...&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;也许你看到上面的名字觉得有点逗，其实很实在。本人电脑任务栏上必然有这些工具，随点随用，不亦乐乎。相信工作几年的人应该有此体会，刚入行的以后慢慢就知道了。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;以画图举例，说到截图，也许你会说Snagit，它是强大，但点来点去麻烦的很，还倒不如直接PrintScreen+Ctrl+V方便&amp;mdash;&amp;mdash;平时又不需要去演示，谁需要截的那么细致啊。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;还有个记事本，就强大了，有心情的时候完全可以用记事本写代码假装高人，Word是很强大，但能写代码么？嘿嘿。平时灵光一闪有个绝好的点子，用记事本记下就记下来，不会丢掉；换做其他，恐怕工具还没打开，点子没了，郁闷就来了。&lt;/span&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;strong&gt;&lt;a id="P6_Label"&gt;&lt;/a&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;6，帮助别人，向他人学习&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;向他人学习，很多人都能做的到，实际未必。事实上如果你面前有个牛人，好学的你自然会向他请教学习，这只能算是好学的一小部分。因为跟你差不多的和比你差的总是占大部分。&lt;/p&gt;&lt;p&gt;俗话说：&amp;ldquo;三个臭皮匠，顶个诸葛亮&amp;rdquo;，并不是说三个臭皮匠加起来就真的比诸葛亮厉害，而是说每个人都有可取之处，世上没有十全十美的人。就算你是公司的首席架构师又如何，总有你不会的东西。所以遇到跟你差不多的人，尤其是有些微妙的竞争关系的人，不要不服，一定虚心向人学习，这样子有可能你学到了他会的，而他没有学到你会的，结果你就真的超过了他。&lt;/p&gt;&lt;p&gt;通常帮助别人时你一定在某一方面比别人强，这时也许你感觉很舒服，那人也很感激你。这时你要注意多些赠品，比如帮他检视代码啊，指出不足啊，最后一定发掘他的优点，顺便看看自己有没有。这样子既帮了别人，又帮了自己，只有自己知道是双赢并窃喜，结束时还可以故作大方地说&amp;ldquo;不客气&amp;rdquo;或者&amp;ldquo;不用找零了&amp;rdquo;！&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;strong&gt;&lt;a id="P7_Label"&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;7，贪多嚼不烂&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;上次有个新人说他现在要学习HTML+CSS+JavaScript+Asp.NET+C#+SQLServer，感觉学不过来，问我该怎么办。我说丢掉几个，他说学了一些，丢掉觉得可惜，又说有人给他的工作就需要这些，我还说丢掉大部分，主学一个，辅学另一个做调节，其他当兴趣；如果有人催，就说自己不会。最后他又说他问了好几个工作过的人，答案都这样。我说这就对了，贪多嚼不烂，听我们的，没有错。&lt;/p&gt;&lt;p&gt;很多人经常会接触的很多东西，好奇心促使他什么都想学，他就同时什么都学，结果什么也学不会。人的精力毕竟有限，所以同时只能学习一门技术，能力好的可以学两门。其实，以我自己的经验来看，如果学精了一门，与之类似的技术，就算你根本都没接触过，你也可以声称自己精通它。这不是吹牛，所谓万变不离其踪。对于一门基础，只知万变顶多算入门；知其踪就可算精通了。然后遇到大同小异的东西，知其根难道还怕不知其表么？！&lt;/p&gt;&lt;p&gt;举个例子，C#与Java之争由来已久，每次都口水漫天，这只能说大多数人都很水。真正懂C#或Java的人不会互喷（因为他都懂了，虽然他可能没用过C#或Java）&amp;mdash;&amp;mdash;你见过C#或Java之父相互口水的么？！&lt;/p&gt;&lt;div id="_mcePaste" class="mcePaste" style="position: absolute; width: 1px; height: 1px; overflow: hidden; top: 0px; left: -10000px;"&gt;﻿&lt;/div&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;strong&gt;&lt;a id="P8_Label"&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;8，总结&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;好了，今天就到这里。如果你觉得有什么不妥的地方，请你多多指正。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/niyw/aggbug/1863903.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/niyw/archive/2010/11/03/1863903.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/niyw/archive/2010/10/31/1863908.html</id><title type="text">WPF之路——WPF布局系统</title><summary type="text">前言前段时间忙了一阵子Google Earth，这周又忙了一阵子架构师论文开题报告，现在终于有时间继续&lt;WPF之路&gt;了。先回忆一下上篇的内容，在《从HelloWorld到WPF World》中，我们对WPF有了个大概的了解，并了解了初学WPF时应该从哪些知识点入手。今天我们就从最基本的知识点之一布局系统来继续学习WPF，主要包括如下内容。 0，什么是布局1，基本元素—&amp;md...</summary><published>2010-10-31T14:04:00Z</published><updated>2010-10-31T14:04:00Z</updated><author><name>倪大虾</name><uri>http://www.cnblogs.com/niyw/</uri></author><link rel="alternate" href="http://www.cnblogs.com/niyw/archive/2010/10/31/1863908.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/niyw/archive/2010/10/31/1863908.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;span class="LW_CollapsibleArea_Title" style="font-size: 14pt;"&gt;前言&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 12pt;"&gt;前段时间忙了一阵子Google Earth，这周又忙了一阵子架构师论文开题报告，现在终于有时间继续&amp;lt;WPF之路&amp;gt;了。先回忆一下上篇的内容，在《&lt;a href="http://www.cnblogs.com/niyw/archive/2010/10/17/1852622.html"&gt;从HelloWorld到WPF World&lt;/a&gt;》中，我们对WPF有了个大概的了解，并了解了初学WPF时应该从哪些知识点入手。今天我们就从最基本的知识点之一布局系统来继续学习WPF，主要包括如下内容。 &lt;/span&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;/p&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&lt;a href="#P0_Label"&gt;0，什么是布局&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&lt;a href="#P1_Label"&gt;1，基本元素&amp;mdash;&amp;mdash;面板&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&lt;a href="#P2_Label"&gt;2，常用容器控件&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&lt;a href="#P3_Label"&gt;3，测量与排列&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&lt;a href="#P4_Label"&gt;4，基本属性：Alignment,Margin和Pading&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&lt;a href="#P5_Label"&gt;5，附加属性&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&lt;a href="#P6_Label"&gt;6，布局与性能&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&lt;a href="#P7_Label"&gt;7，总结&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;a id="P0_Label"&gt;&lt;/a&gt;&lt;strong&gt;&lt;span class="LW_CollapsibleArea_Title" style="font-size: 14pt;"&gt;0，什么是布局&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;这是一个很简单的问题。简单来说，就是把一些控件有条理的摆放在界面上合适的位置，显然摆的乱七八糟不能算布局。在WPF中，这个条理与WinForm中略有不同，让我们看个很简单的界面：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://pic002.cnblogs.com/images/2010/141116/2010103015014834.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;这样子的界面大家在熟悉不过了。依图所示，WPF先用蓝线（假设的线）将界面划分为上下两部分，然后再有红线划分出多个方格，最后放入控件，其中每部分中的控件或划分的空格只能纵向排列，或横向排列，不能有其他选择。大多数情况下，WPF程序界面上的控件都要按照此种递归的方法逐个排列，最终形成所看到的界面。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a id="P1_Label"&gt;&lt;/a&gt;&lt;strong&gt;&lt;span class="LW_CollapsibleArea_Title" style="font-size: 14pt;"&gt;1，基本元素&amp;mdash;&amp;mdash;面板&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;在上节中我们了解了WPF布局原理，这可以简单理解为大控件中按排或列放入小控件，小控件在按照同样规则放入更小控件。这种能放入其他控件的控件是WPF布局系统中的基本元素&amp;mdash;&amp;mdash;面板。面板是用来放东西的，既包括控件元素，也包括面板自己。面板不仅能承载其他子元素(控件)，还能控制子元素的大小，位置以及如何排列。例如上述例子中，蓝线划分的面板控制子元素只能上下排列，而红线划分的面板控制的子元素只能横向排列。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WPF默认提供了几种面板都是从基面板(Panel)继承而来，看一下它们的继承链。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.threading.dispatcherobject.aspx"&gt;System.Windows.Threading.DispatcherObject&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.dependencyobject.aspx"&gt;System.Windows.DependencyObject&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.media.visual.aspx"&gt;System.Windows.Media.Visual&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.uielement.aspx"&gt;System.Windows.UIElement&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.frameworkelement.aspx"&gt;System.Windows.FrameworkElement&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: #33cccc;"&gt;&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.controls.control.aspx"&gt;System.Windows.Controls.Control&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="selflink"&gt;System.Windows.Controls.Panel&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.controls.canvas.aspx"&gt;System.Windows.Controls.Canvas&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.controls.dockpanel.aspx"&gt;System.Windows.Controls.DockPanel&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.controls.grid.aspx"&gt;System.Windows.Controls.Grid&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.controls.stackpanel.aspx"&gt;System.Windows.Controls.StackPanel&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.controls.virtualizingpanel.aspx"&gt;System.Windows.Controls.VirtualizingPanel&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 12pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.controls.wrappanel.aspx"&gt;System.Windows.Controls.WrapPanel&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: 14pt;"&gt;&lt;strong&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;a id="P2_Label"&gt;&lt;/a&gt;&lt;span style="font-size: 14pt;"&gt;&lt;strong&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;2，常用容器控件&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;WPF默认提供了数种布局控件，常用的包括如下几种：&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;table style="margin-left: auto; margin-right: auto;" border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;名称&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;用法&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;说明&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;Canvas&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/141116/2010103016281658.png" alt="" /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;此面板可承载任意元素，包括控件，图形，甚至文字。各种元素依据屏幕坐标确定位置。&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;DockPanel&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/141116/2010103016301794.png" alt="" /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;此面板可指定元素的排列停靠方式，每个子元素的排列方式可以不同。&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;Grid&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/141116/2010103016302938.png" alt="" /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;此面板使子元素按照纵横网格排列。&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;StackPanel&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/141116/2010103016303924.png" alt="" /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;此面板使子元素按照水平或垂直方向排列，两个方向只能选其一。&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;VirtualizingStackPanel&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/141116/2010103016304890.png" alt="" /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;与StackPanel相同，不同之处在于它可以使内容虚拟化。&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;WrapPanel&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/141116/2010103016305845.png" alt="" /&gt;&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;使子元素按照水平或垂直方向排列，在行或列处换行或列，依旧按照水平或垂直方向从左到右或从上到下排列。&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;a id="P3_Label"&gt;&lt;/a&gt;&lt;span style="font-size: 14pt;"&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14pt;"&gt;&lt;strong&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;3，测量与排列&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;当我们在面板上放入子元素，并设置相应的属性时，WPF的布局系统自动为我们完成2个过程：测量和排列，这是两个非常重要的过程。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;由于WPF界面元素有很多与布局有关的属性，如坐标，大小，对齐方式，相对位置，间距等。首先这些属性使用的是与设备无关的分辨率单元，这导致同样大小的元素在不同界面上显示的效果可能不同；其次每个属性值有一定的优先级，例如Button的Height和Width属性优先于Stretch属性，&lt;span id="xn22_f0c5268e7b78dc190f9221227d53df42" class="sentence"&gt;如果设置 Height, Width 以及 &lt;span class="code"&gt;Stretch&lt;/span&gt;，会导致 &lt;span class="code"&gt;Stretch&lt;/span&gt;被忽略。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span class="sentence" style="font-size: 12pt;"&gt;因此，尽管在设计时指定了属性值，布局系统依然需要重新计算每个子元素在界面上的实际大小，位置，边距等值，这些值被称为&amp;ldquo;FinalSize&amp;rdquo;。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a id="P4_Label"&gt;&lt;/a&gt;&lt;strong&gt;&lt;span class="LW_CollapsibleArea_Title" style="font-size: 14pt;"&gt;4，基本属性：Alignment,Margin和Pading&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;在设计UI时，WPF为我们提供了一些属性用于精确定位元素，其中最常用的有三个：Alignment(包括水平，垂直)，Margin，Pading，具体用法如下：&lt;/span&gt;&lt;/p&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;名称&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;说明&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;Alignment&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;子元素在水平(垂直)方向的对齐方式，有左对齐，右对齐（顶端对齐，底部对齐），中间对齐，拉伸填充等四种方式。&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;Margin&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;用于指定元素与其子级或同级之间的距离，包括上下左右四个值。也&lt;span id="xn53_7eb545eb060c891fe4567b11c2138452" class="sentence"&gt;可通过使用 &lt;span class="code"&gt;Margin="20"&lt;/span&gt; 同时指定四个值。&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;span style="font-size: 12pt;"&gt;Pading&lt;/span&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&lt;span id="xn64_4ec42a9791287087a5c275164733de9a" class="sentence"&gt;Padding 在大多数方面类似于 Margin，&lt;/span&gt;&lt;span id="xn65_a1774415f58d10729f35051150490cde" class="sentence"&gt;只有少数元素有（公开），用于&lt;/span&gt;&lt;span id="xn66_4eb97d842b87ba9fc26d27f957b35bce" class="sentence"&gt;将子元素的有效大小增大指定的厚度。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a id="P5_Label"&gt;&lt;/a&gt;&lt;span style="font-size: 14pt;"&gt;&lt;strong&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;5，附加属性&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;通过上面我们了解到子元素通过一些属性值的设置实现在面板上布局，比如Alignment对齐属性，Dock停靠排列属性。这些属性不属于子元素本身，而依赖与所在的父元素。比如同样是Button，在DockPanel中有Dock属性，而在Grid中就没有。这些属性的存在依赖与父元素，在WPF中称做&amp;ldquo;附加属性&amp;rdquo;。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;附加属性的用途是允许不同的子元素为实际在父元素中定义的属性指定唯一值，目的是&lt;span id="xn7_fccbdbaacaaf1ebfb251873ca9e7cdc5" class="sentence"&gt;让子元素通知父元素它将如何在界面中呈现。&lt;/span&gt;&lt;span id="xn8_2285f3030d1610e6aeb04530d4b6cbe5" class="sentence"&gt;如上面提到的DockPanel.Dock 属性&lt;/span&gt;&lt;span id="xn9_01ee7a53643bbd5aca1c7e9b69ececfa" class="sentence"&gt;，因为它将在 DockPanel 中包含的元素上设置，而不是在 DockPanel 本身设置。注意，相对于子元素，父元素提供的附加属性相当于全局属性。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a id="P6_Label"&gt;&lt;/a&gt;&lt;span style="font-size: 14pt;"&gt;&lt;strong&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;6，布局与性能&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;通过上面我们了解到，当给界面元素的布局属性赋值时，布局系统需要重新计算和排列所有子元素的&amp;ldquo;FinalSize&amp;rdquo;(因为改变影响不可知)。这是一个递归的过程。如果不注意，可能会带来性能问题。因此在设计时应注意下面几点：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;1，&lt;span id="xn90_3d9af85e4716ff08e0e76fe7146b0743" class="sentence"&gt;应注意哪些属性值更改会引起执行布局系统的递归更新；&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;&lt;span class="sentence"&gt;2，&lt;/span&gt;&lt;span id="xn95_79d1518d52b56134c4345c28cf3cbbf5" class="sentence"&gt;如有可能，应使用 RenderTransform 而不要使用 LayoutTransform；&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span id="xn99_135ba669bcffcbdeb3cdbe5b6491a186" class="sentence" style="font-size: 12pt;"&gt;3，避免不必要地调用 UpdateLayout，因为UpdateLayout强制调用布局系统的递归更新；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span id="xn102_55960661c615bad9e14a8a6f024c1fc9" class="sentence" style="font-size: 12pt;"&gt;4，当包含大量元素集合时，请使用 VirtualizingStackPanel虚拟化元素；&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a id="P7_Label"&gt;&lt;/a&gt;&lt;span style="font-size: 14pt;"&gt;&lt;strong&gt;&lt;span class="LW_CollapsibleArea_Title"&gt;7，总结&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;&lt;hr class="LW_CollapsibleArea_Hr" /&gt;&lt;p&gt;&lt;span style="font-size: 12pt;"&gt;通过本文，我们大概了解了WPF的布局系统，常用的布局面板，与布局有关的几个属性，以及设计开发UI时的注意事项。这些内容很多与WinForm中的相关概念相通，可以说是旧瓶装新酒，稍加思考，并不难理解；如果深入了解，会发现与WinForm截然不同。但作为初学者，如果能灵活使用文中所讲的知识点，深入理解注意点，对自身的提高还是很有帮助的。&lt;/span&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/niyw/aggbug/1863908.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/niyw/archive/2010/10/31/1863908.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/niyw/archive/2010/10/18/1855095.html</id><title type="text">由感而发：离职的第四个理由</title><summary type="text">今天看到园子里周金根的《个人管理：程序员应不应该离职，我该何去何从呢？》一文，读完之后就想写出自己的观点——个人离职的第四个理由——挑战与经历！周兄能在一家公司工作十年，这种经历想来不多，我自问自己做不到。而周兄给出了三个离职理由(职业方向，环境氛围，工资奖金)也很恰当，在赋以充分的说明，更引起了大家的共鸣。然而人生就是如此吗？！我相信人与人...</summary><published>2010-10-18T14:06:00Z</published><updated>2010-10-18T14:06:00Z</updated><author><name>倪大虾</name><uri>http://www.cnblogs.com/niyw/</uri></author><link rel="alternate" href="http://www.cnblogs.com/niyw/archive/2010/10/18/1855095.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/niyw/archive/2010/10/18/1855095.html"/><content type="html">&lt;p&gt;今天看到园子里&lt;a href="http://www.cnblogs.com/zhoujg/"&gt;周金根&lt;/a&gt;的《个人管理：程序员应不应该离职，我该何去何从呢？》一文，读完之后就想写出自己的观点&amp;mdash;&amp;mdash;&lt;strong&gt;个人离职的第四个理由&amp;mdash;&amp;mdash;挑战与经历&lt;/strong&gt;！&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;周兄能在一家公司工作十年，这种经历想来不多，我自问自己做不到。而周兄给出了三个离职理由(职业方向，环境氛围，工资奖金)也很恰当，在赋以充分的说明，更引起了大家的共鸣。然而人生就是如此吗？！&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;我相信人与人的不同，也喜欢脚踏实地的做事，但让我数十年做同一种工作，我肯定做不到，不是没有那份耐心，而是希望有更多的挑战，有更多的经历，有更广阔的视野&lt;/strong&gt;。所以适当的时候，我会离职。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;自毕业到现在的第三份工作，没份工作都在一个全新的行业，做着完全不同的事，而在每次离职前，自问不会留下任何遗憾。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;也许工作N年的人更容易与周兄产生共鸣，也许刚毕业或还没有工作的人更容易与我一拍而合。原因想来很简单，数年社会的洗礼早以洗静了大家原有的多姿多彩；成家后的生活琐事不知不觉间磨平了原有的棱角；日常的柴米油盐让你需要为锱铢忙碌；而这些离刚毕业或没毕业的人尚有一段距离，所以他们还有那份火热的朝气。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;但你有这样想过吗？当数十年过后，也许你成为了行业内的专家，也许你成为了劳模，可除了这些你还会什么呢？！这是你的一技之长，能满足你的生活物质需要，精神上的呢？作为程序员，只懂得代码，并且很精通，这听起来很正常，可&lt;strong&gt;有没有想过在自己的01010011世界中加入&amp;ldquo;明月几时有，把酒问青天&amp;rdquo;或者&amp;ldquo;噫吁嚱，危乎高哉！蜀道之难，难于上青天！&amp;rdquo;！&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;也许你我注定是凡人，成就不了轰轰烈烈的事业，但至少不能困顿于柴米油盐。外面的世界很精彩，何必做那一方井底之蛙。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;况且，人生的哲学是通过不断地磨练才能练成的。终有一天你会无力工作，然而人生经历淬炼出的智慧则越久越显得光芒四射。中国有句古话：&amp;ldquo;家有一老，如有一宝&amp;rdquo;，但生活中更多的是倚老卖老的&amp;ldquo;遭老头&amp;rdquo;或者&amp;ldquo;老不死的&amp;rdquo;，你想成为那者呢？至少我会努力成为&amp;ldquo;一宝&amp;rdquo;。而想成为&amp;ldquo;一宝&amp;rdquo;，需要有大智慧，这些智慧及来自于先天，更来自于不断跳战的人生。相信长久蜗居一方的人很难知道什么是海阔天空。&lt;strong&gt;纵然你数十年成就一方专家，最终也难免是&amp;ldquo;河伯之于海若&amp;rdquo;。&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;然人与人之不同在于天性，不可一概而论，只要不被岁月磨平原有的天性，都是值得庆贺的。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;脑中响起那首《海阔天空》，始终坚持梦想，永远敢于跳战新的目标!!&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;em&gt;注：&lt;/em&gt;1，&amp;ldquo;噫吁嚱，危乎高哉！蜀道之难，难于上青天！&amp;rdquo;见《李白。蜀道难》；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2，&amp;ldquo;河伯，海若&amp;rdquo;见《庄子。秋水》；&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;---------------------------------------------------------------------------------------------------------------------------------------&lt;/p&gt;&lt;p&gt;后补1&amp;mdash;&amp;mdash;&amp;ldquo;&lt;span id="comment_body_1937360" class="blog_comment_body"&gt;对我来说，离职的最大的理由是可以和家人在一起.&lt;/span&gt;&amp;rdquo;&lt;/p&gt;&lt;p&gt;人生最重要最切实的莫过于家人，我也会为此做出选择！&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;后补2&amp;mdash;&amp;mdash;"钱钱钱，钱钱钱"&lt;/p&gt;&lt;p&gt;挑战与经历 Vs 钱&lt;/p&gt;&lt;p&gt;首先二者矛盾吗？不！偏安一隅，顶多是一方霸主；开阔天空则有整个天下！多年稳守一职与挑战更多领域与此雷同；&lt;/p&gt;&lt;p&gt;其次钱虽重要，切莫本末倒置，被它驱使，不然一样得不到钱；&lt;/p&gt;&lt;img src="http://www.cnblogs.com/niyw/aggbug/1855095.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/niyw/archive/2010/10/18/1855095.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/niyw/archive/2010/10/17/1852622.html</id><title type="text">WPF之路——从HelloWorld到WPF World</title><summary type="text">前言有人说到，学习任何一种编程最困难的部分是“Hello World”。这一看似乎很可笑，仔细想来却未必。平时很多我们自认为很简单的东西也许恰恰是最困难的东西，比如C#中的一些基本概念，我们天天都在用，可你真的都理解他们吗？！对很多人来说恐怕要打个问号了。最近开始学习使用WPF，WPF是什么？网上有很多文章，在此就不赘述了。一切还是从“Hello World”开始，然而因为有了上面的经...</summary><published>2010-10-17T13:54:00Z</published><updated>2010-10-17T13:54:00Z</updated><author><name>倪大虾</name><uri>http://www.cnblogs.com/niyw/</uri></author><link rel="alternate" href="http://www.cnblogs.com/niyw/archive/2010/10/17/1852622.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/niyw/archive/2010/10/17/1852622.html"/><content type="html">&lt;p&gt;&lt;strong&gt;前言&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;有人说到，学习任何一种编程最困难的部分是&amp;ldquo;Hello World&amp;rdquo;。这一看似乎很可笑，仔细想来却未必。平时很多我们自认为很简单的东西也许恰恰是最困难的东西，比如C#中的一些基本概念，我们天天都在用，可你真的都理解他们吗？！对很多人来说恐怕要打个问号了。&lt;/p&gt;&lt;p&gt;最近开始学习使用WPF，WPF是什么？网上有很多文章，在此就不赘述了。&lt;/p&gt;&lt;p&gt;一切还是从&amp;ldquo;Hello World&amp;rdquo;开始，然而因为有了上面的经历，一切真的都变得不同了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Hello World&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如题，在优秀的IDE环境中，做一个简单的Hello World应用程序是如此的简单，仅仅用鼠标拖一个控件，在属性栏中输入&amp;ldquo;Hello World&amp;rdquo;，然后F5，OK，一切都完成了。&lt;/p&gt;&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://pic002.cnblogs.com/images/2010/141116/2010101522202788.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;这一切真的太简单了，就跟当年学习VB或C#一样，看起来没有任何不同，然而现在你还会说VB的Hello World与C#的Hello World是一回事么？！答案很显然。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;什么是Hello World&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;有个笑话讲到，一个退休的程序员，退休后练习书法，提笔一挥，纸上赫然出现一行字&amp;mdash;&amp;mdash;Hello World。第一个写&amp;ldquo;Hello World&amp;rdquo;的人也许是个天才。一粒沙中看世界，这个简单到一行代码甚至没有代码就能实现的程序向初学编程的人打开了一道便捷之门，给初学者足够的空间去思考有限的问题，一窥其后万千变化的世界。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Hello World有什么&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;Shift+F5，停止程序运行，让我们一起看看这个程序中有什么。先看文件结构：&lt;/div&gt;&lt;div&gt;&lt;table style="width: 1149px; height: 186px;" border="0"&gt;&lt;tbody&gt;&lt;tr align="left" valign="top"&gt;&lt;td width="200"&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/141116/2010101621480192.png" alt="" /&gt;&lt;/td&gt;&lt;td&gt;在解决方案资源管理器中，我们不难发现与WinForm相比，WPF程序多出了一种文件Xaml。先打开我们熟知的.cs代码文件，发现里面空无一物，甚至看不到承载Hello World的控件，结合Asp.Net的经验，我们在Xaml中发现了&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;pre class="brush:csharp"&gt;    &amp;lt;Grid&amp;gt;&lt;br/&gt;        &amp;lt;TextBlock Text="Hello World" /&amp;gt;&lt;br/&gt;    &amp;lt;/Grid&amp;gt;&lt;br/&gt;&lt;/div&gt;由此我们可以认为微软通过结合Asp.Net与WinForm的优点打造了全新的，而相比二者，WPF最核心的部分便是Xaml。&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;发现Xaml&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;那么什么是Xaml呢？MSDN中解释到：&lt;span id="xn1_61362c6098319379b5c6d8cd5122218d" class="sentence"&gt;可扩展应用程序标记语言 (XAML) 是声明性应用程序编程标记语言，WPF提供对可扩展应用程序标记语言 (XAML) 语言支持，使WPF得以实现，这个解释有点抽象。事实上，如果有Asp.Net基础，我们则可以简单的认为WPF是以Asp.Net方式开发WinForm；如果有标记语言的基础，则可以简单认为Xmal以标记语言的方式实现WPF中的UI，然后由微软把UI和代码联系起来；如果什么都没有，那就把看到的网页关了，好好学习吧^_^。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;开启WPF World&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;元素树&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们知道，WPF的核心是Xaml。Xaml想做网页一样，将UI分割为不同大小的块，以一定方式组合，便成了我们看到UI基本框架，然后在通过美工的合作，成为最终呈现在我们面前的用户交互界面。Xaml中的每种元素代表UI上的一个基本元素，那么Xaml是以何种方式组织这些元素，并最终构成向用户交付的UI呢？看下图。&lt;img src="http://pic002.cnblogs.com/images/2010/141116/2010101720120782.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;如图所示，WPF以有序的方式按树形结构组合每个界面元素。界面中每个元素都有唯一的父节点，并可能有多个子节点。图中第3部分就是Hello World示例的树结构示意图。当然，WPF文档结构远比例子中复杂的多，不过作为入门，这些不在今天的讨论范围呢。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;基元素&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;现在改动一下程序，我们添加一个按钮，点击该按钮，显示一个消息框。&lt;img src="http://pic002.cnblogs.com/images/2010/141116/2010101720391484.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;在上面我们了解到WPF中Xaml负责UI，cs负责实现逻辑(显示消息框)。那么它们是如何关联起来的呢(请注意图中蓝线)？原来在WPF中，凡是与UI元素类均从一个基元素继承&amp;mdash;&amp;mdash; &lt;span&gt;&lt;a href="http://msdn.microsoft.com/zh-cn/library/system.windows.dependencyobject.aspx"&gt;&lt;span style="color: #1364c4;"&gt;DependencyObject&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;而来，这些类分别在cs和xaml中有相同签名的实现。我们在开发过程中只需要取相同的名字，WPF会自动替我们完成关联工作。&lt;/p&gt;&lt;p&gt;&lt;em&gt;注意：如果在C#代码中将button1_Click改为OnBtnClick，Xaml中不会自动改&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;属性&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;现在仔细观察一下IDE自动生成的代码，如果Asp或HtmlXml一样，我们会发现每个元素标签，除了标签名外都包含一些属性。除了在C#中我们熟知的Text="Hello World"，Name="button1"外还包含Asp.NET中常见的Margin属性(用于说明Button在父容器中与其他元素的间隔距离)。前者与C#中的属相相同，后者则不属于对象本身，依赖于父元素，在WPF中成为附加属性(比如，如果Button不在一个父元素(Grid)中，那么它与其他元素就无所谓相对距离了)。&lt;/p&gt;&lt;p&gt;在上小节中，我们知道WPF负责将Xaml元素与C#中的类一一对应起来，在Xmal中改变Button.Height的值时，cs中同样会做相应的改动，那么它们是如何实现的呢？原来WPF提供了一套属性系统，该系统提供一种方法来基于其他输入的值计算属性值。有了这套系统，我们在Xmal与cs之间访问属性时WPF会自动通知彼此，支持&lt;span id="xn2_1b271ef7719643e5cd73689d741230d5" class="sentence"&gt;这些服务的属性通常称为依赖属性。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;样式和模板&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;想象一下我们继续修改Hello World程序，如果需要添加10个或100个相同Button，这些Button针对不同的用户有不同的样式。那么我们该如何支持这些样式呢？是在xmal中一个一个的写吗？当然不可能。既然Xaml类似于Asp.Net，那么我们不难想到网页中常用的CSS，在WPF中同样有属于Xaml的Css，并且更强大，那就是样式和模板。&lt;/p&gt;&lt;p&gt;WPF样式设置和模板提供了一套功能（样式、模板、触发器和演示图板），让我们能够使用这些功能创建更好的视觉效果，也可以为创建统一外观，并且能够在应用程序内部和应用程序之间共享这些样式和模板，从而提供工作效率。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;资源&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在上小节中，我们提到了样式和模板，这些在WPF中属于资源。除此之外，WPF中的资源也包括C#中我们通常理解的文件，多媒体，数据等。只是在WPF中资源可分为静态资源和动态资源。从名字上很好理解它们的区别，一个性能好点，一个更灵活。做为入门，在使用时，是否需要实时更新资源可作为我们选择静态资源和动态资源的依据。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;总结&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;学到了什么&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;通过上面一系列描述，我们发现了WPF中的一些基本概念：Xaml，元素树，基元素，属性，样式和模板，资源。这些都是初学WPF时最早接触到的内容。因篇幅所限，只能对这些内容做一个大概的介绍，使得我们能够从中一窥WPF的样貌。但做为初学者，充分理解把握这些内容是进一步学好WPF的关键。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;如何学习&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在上面的学习过程中，我们不难发现，学习任何一门技术都要从最简单的地方开始，然后通过仔细观察，发现问题，思考问题，并最终解决问题。其中最重要的是要勤于思考，而不是浮于表面。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;下一步该做什么&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;今天我们从整体上对WPF有个粗略的了解，并发现了一些基本概念。虽然还有很多重要的内容如数据绑定，事件路由，线程模型等没有涉及到，但是本着贪多嚼不烂的原则，下一步我们应该对今天所涉及到的每个概念做深入的学习，然后经过反复的联系，最终能真正了解它们。&lt;/p&gt;&lt;div id="_mcePaste" class="mcePaste" style="position: absolute; width: 1px; height: 1px; overflow: hidden; top: 0px; left: -10000px;"&gt;﻿&lt;/div&gt;&lt;img src="http://www.cnblogs.com/niyw/aggbug/1852622.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/niyw/archive/2010/10/17/1852622.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/niyw/archive/2010/10/10/1847253.html</id><title type="text">.NET中的设计模式——一步步发现装饰模式</title><summary type="text">文章通过循序渐进的方式逐步暴露问题(各种继承，子类，代码像麻花一样挤在一起)，然后用装饰模式解决(把每种需求单独构建成组件，然后像搭积木一样完成工作)，最后联系实际说明装饰模式的真正含义.</summary><published>2010-10-10T14:24:00Z</published><updated>2010-10-10T14:24:00Z</updated><author><name>倪大虾</name><uri>http://www.cnblogs.com/niyw/</uri></author><link rel="alternate" href="http://www.cnblogs.com/niyw/archive/2010/10/10/1847253.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/niyw/archive/2010/10/10/1847253.html"/><content type="html">&lt;p&gt;&lt;strong&gt;前言&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;过去我的一个朋友常说，学习任何编程语言最困难的部分是运行&amp;ldquo;Hello World&amp;rdquo;，之后一切都很容易。多年以后，我才意识到他说的很对。学习设计模式的基本目标是要用它，尤其是帮助那些有扎实的OOP基础，而对设计模式很困惑的人在设计中应用它。我不会为不同设计模式写很全面的参考，但我希望这些文章能让你入门。设计模式与特定的语言无关。虽然我用C#写了很多示例，但我尽量避免一些C#特有的结构，因此它面向大部分人，尤其是使用C++的人。&lt;/p&gt;&lt;p&gt;装饰器模式允许我们动态为对象添加行为。下面我们先介绍一个场景，然后寻找替代方法。这会帮助我们认清该模式的真实用途，尤其在灵活性这方面。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;思考过程&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;今天我们参考的不是一个实际的场景，有时可能会很奇怪，但它会帮助我们弄清这个模式及相关概念。我们的目标是添加将不同来源的信息存储到磁盘文件上的功能。所以，第一步我们定义一个接口，并实现它。&lt;span style="color: #993300;"&gt;&lt;strong&gt;IMessageWriter&lt;/strong&gt;&lt;/span&gt;和&lt;span style="color: #993300;"&gt;&lt;strong&gt;IMessageReader&lt;/strong&gt;&lt;/span&gt;接口分别用于写入和读取信息，他们的实现如下：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;    interface IMessageWriter {&lt;br/&gt;        string Message { set; }&lt;br/&gt;        void WriteMessage(string filePath);&lt;br/&gt;    }&lt;br/&gt;    class MessageWriter : IMessageWriter {&lt;br/&gt;        private string message;&lt;br/&gt;        public string Message { set{message =value;} }&lt;br/&gt;        public virtual void WriteMessage(string filePath) {&lt;br/&gt;            File.WriteAllText(filePath, message);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;    interface IMessageReader {&lt;br/&gt;        string ReadMessage(string filePath);&lt;br/&gt;    }&lt;br/&gt;    class MessageReader : IMessageReader {&lt;br/&gt;        public virtual string ReadMessage(string filePath) {&lt;br/&gt;            if (File.Exists(filePath))&lt;br/&gt;                return File.ReadAllText(filePath);&lt;br/&gt;            return null;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;/div&gt;&lt;p&gt;信息作为&lt;span style="color: #993300;"&gt;Message&lt;/span&gt;属性存储，&lt;span style="color: #993300;"&gt;MessageWriter&lt;/span&gt;的方法&lt;span style="color: #993300;"&gt;WriteMessage&lt;/span&gt;把它写到指定的文件。同样，&lt;span style="color: #993300;"&gt;MessageReader&lt;/span&gt;的方法&lt;span style="color: #993300;"&gt;ReadMessage&lt;/span&gt;从指定的文件读取，并以字符串的形式返回。现在假设客户提出了新需求。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;对某些信息在读和写文件之前，我们需要验证用户；&lt;/li&gt;&lt;li&gt;对某些信息我们希望加密后保存，来防止别人读取，并且我们需要以64位编码保存加密信息；&lt;/li&gt;&lt;li&gt;对某些信息，我们都需要这些功能；&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;很奇怪吧，呵呵，首先我们不用装饰器分析不同的解决方案，这会使我们对这个简单的设计模式认识更加清晰。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;传统解决方案&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;你决定在原来行为上使用继承。你从&lt;span style="color: #993300;"&gt;MessageWriter&lt;/span&gt;继承&lt;span style="color: #993300;"&gt;EncryptedMessageWriter&lt;/span&gt;来实现加密行为。 &lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;    class EncryptedMessageWriter : MessageWriter {&lt;br/&gt;        public override void WriteMessage(string filePath) {&lt;br/&gt;            //加密消息&lt;br/&gt;            //转换到64位编码&lt;br/&gt;            Message = "base64StringYouGotFromAboveCode";//存储信息&lt;br/&gt;            base.WriteMessage(filePath);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;/div&gt;&lt;p&gt;同样，你从&lt;span style="color: #993300;"&gt;EncrytedMessageWriter&lt;/span&gt;继承&lt;span style="color: #993300;"&gt;SecureMessageWriter&lt;/span&gt;来实现用户验证。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;    class SecureMessageWriter : EncryptedMessageWriter {&lt;br/&gt;        public override void WriteMessage(string filePath) {&lt;br/&gt;            if (ValidateUser())&lt;br/&gt;                base.WriteMessage(filePath);&lt;br/&gt;            else&lt;br/&gt;                Console.WriteLine("No message saved,user validation failed.");&lt;br/&gt;        }&lt;br/&gt;        private bool ValidateUser() {&lt;br/&gt;            //验证用户,失败返回false&lt;br/&gt;            return true;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;/div&gt;&lt;p&gt;现在我们能写入加密的信息，或经过用户验证后的加密信息。那么如果需要写入一些只需要用户验证而不需要加密的简单文本信息时，我们该怎么办？你可以在&lt;span style="color: #993300;"&gt;EncryptedMessageWriter&lt;/span&gt;中写入一些丑陋的判断，在不需要加密的时候跳过加密。假设遇到此类情况你还这么做，那么那些操作换个顺序呢，例如我们想先加密后验证，如果验证失败，则除64位编码加密消息外在做点别的。很显然，上面的组织结构无法处理这种情况。谁能阻止用户提出更多的需求，像消息需要数据签名，大消息需要压缩或不需要加密，对于某些信息，写到磁盘后，你必须在消息队列中输入文件路径和时间戳以便其他程序读取，甚至写到数据库中，等等等等？！显然不能。&lt;/p&gt;&lt;p&gt;让我们只关注验证，忽略其他细节，评估一下你面对情况的复杂性和严重性。目前，我们在加密消息时实现了用户验证。现在我们需要满足其他相同的功能，如：&lt;span style="color: #993300;"&gt;CompressedMessageWriter&lt;/span&gt;,&lt;span style="color: #993300;"&gt;DigitallySignedMessageWriter&lt;/span&gt;等。你唯一能做的是实现&lt;span style="color: #993300;"&gt;SecureCompressedMessageWriter&lt;/span&gt;,&lt;span style="color: #993300;"&gt;SecureDigitallySignedMessageWriter&lt;/span&gt;等。同样对其他大量的组合，像压缩加密信息，简单信息压缩等等。天哪，你真的坠入&amp;ldquo;子类地狱&amp;rdquo;了。&lt;/p&gt;&lt;p&gt;第二个解决方案是写一个非常大的&lt;span style="color: #993300;"&gt;MessageReader&lt;/span&gt;，处理所有提到的需求功能。随着时间流逝，它变得越来越复杂，越来越难以维护&amp;mdash;&amp;mdash;非常不推荐这样。&lt;/p&gt;&lt;p&gt;第三个解决方案可能是上面两种方案的合并，这可能是治标不治本。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;引入装饰器模式&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这恰恰是装饰器模式解决的问题。如果你仔细观察上面采用继承的解决方案，你会认识到问题的根源是继承带来的静态关联。这些关联被嵌入到类之间，并且不能在运行时改变。装饰器用包含替换关联，而包含是一种非常灵活且在运行时能被更新的对象关联。&lt;/p&gt;&lt;p&gt;首先让我们看看装饰器模式究竟是什么。下面是装饰器模式的类图。&lt;/p&gt;&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://pic002.cnblogs.com/images/2010/141116/2010101016540593.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;四个参与者:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Component&lt;/strong&gt;:定义一个对象接口，可以动态的给对象添加职责. 在我们的例子中是&lt;span style="color: #993300;"&gt;IMessageWriter&lt;/span&gt;和&lt;span style="color: #993300;"&gt;IMessageReader&lt;/span&gt;；&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ConcreteComponent&lt;/strong&gt;: 定一个实现Component接口的对象。这个对象会被装饰，但它不会包含任何装饰者的信息，而装饰者不会访问它的实现。在我们例子中是&lt;span style="color: #993300;"&gt;MessageWriter&lt;/span&gt;和&lt;span style="color: #993300;"&gt;MessageReader&lt;/span&gt;。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Decorator&lt;/strong&gt;: 包含一个Component对象的引用，定义一个与Component一致的接口。所以它包含一个指向基本行为的引用，并且实现了相同的接口，因此能被Component自己访问。客户端代码期望Component能不需要关心装饰者之间的差别处理它们。&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ConcreteDecorator&lt;/strong&gt;: 它向Component添加职责。从Decorator继承来的类可以统一添加新方法的形式添加一些额外的功能。&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;p&gt;到目前为止，我们已有两部分，分别是Component：基本行为，即在我们例子中是&lt;span style="color: #993300;"&gt;IMessageWriter&lt;/span&gt;和用于读的&lt;span style="color: #993300;"&gt;IMessageReader&lt;/span&gt;；和ConcreteComponent，即我们实现的读写行为：&lt;span style="color: #993300;"&gt;MessageWriter&lt;/span&gt;和&lt;span style="color: #993300;"&gt;MessageReader&lt;/span&gt;。&lt;/p&gt;&lt;p&gt;下面是我们实现的&lt;span style="color: #993300;"&gt;SecureMessageWriter&lt;/span&gt;和&lt;span style="color: #993300;"&gt;EncryptedMessageWriter&lt;/span&gt;。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;class SecureMessageWriter : IMessageWriter {&lt;br/&gt;        private string message;&lt;br/&gt;        //被装饰者&lt;br/&gt;        private IMessageWriter messageWriter;&lt;br/&gt;        public SecureMessageWriter(IMessageWriter msgWriter) {&lt;br/&gt;            this.messageWriter = msgWriter;&lt;br/&gt;        }&lt;br/&gt;        public string Message {&lt;br/&gt;            set { message = value; }&lt;br/&gt;        }&lt;br/&gt;        public void WriteMessage(string filePath) {&lt;br/&gt;            if (this.ValidateUser()) {//添加新的行为&lt;br/&gt;                //正如你所见,在调用被装饰者的标准方法前我们添加了验证行为&lt;br/&gt;                messageWriter.Message = this.message;&lt;br/&gt;                messageWriter.WriteMessage(filePath);&lt;br/&gt;            }&lt;br/&gt;            else&lt;br/&gt;                Console.WriteLine("");&lt;br/&gt;        }&lt;br/&gt;        private bool ValidateUser() {            &lt;br/&gt;            //验证用户代码&lt;br/&gt;            return true;&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;    class EncryptedMessageWriter : IMessageWriter {&lt;br/&gt;        private string message;&lt;br/&gt;        //被装饰者&lt;br/&gt;        private IMessageWriter msgWriter;&lt;br/&gt;        public EncryptedMessageWriter(IMessageWriter msgWriter) {&lt;br/&gt;            this.msgWriter = msgWriter;&lt;br/&gt;        }&lt;br/&gt;        public string Message {&lt;br/&gt;            set { message = value; }&lt;br/&gt;        }&lt;br/&gt;        public void WriteMessage(string filePath) {            &lt;br/&gt;            this.msgWriter.Message = "encrytedMsgInBase64";//加密信息&lt;br/&gt;            //被装饰得行为&lt;br/&gt;            this.msgWriter.WriteMessage(filePath);&lt;br/&gt;        }&lt;br/&gt;        private string GetPassword() {&lt;br/&gt;            Console.WriteLine("Please provide security password");&lt;br/&gt;            return Console.ReadLine();&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="font-weight: bold;"&gt;这里有问题吗?????&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;p&gt;我刚刚说这个模式有四个参与者，我已向你展示了Component(&lt;span style="color: #993300;"&gt;IMessageReader&lt;/span&gt;，&lt;span style="color: #993300;"&gt;IMessageWriter&lt;/span&gt;)，ConcreteComponent(&lt;span style="color: #993300;"&gt;MessageReader&lt;/span&gt;,&lt;span style="color: #993300;"&gt;MessageWriter&lt;/span&gt;)和ConcreteDecorator(&lt;span style="color: #993300;"&gt;SecureMessageWriter&lt;/span&gt;，&lt;span style="color: #993300;"&gt;EncryptedMessageWriter&lt;/span&gt;)。但&lt;span style="color: #993300;"&gt;Decorator&lt;/span&gt;那里去了？在我们的例子中，我们仅仅添加了已存在的行为，没有引进新的行为。我们没有改变其他结构。在这种情况下，我们忽略了实现&lt;span style="color: #993300;"&gt;Decorator&lt;/span&gt;，并沿用主要层次结构。这里我不在展示读有关的类，它们仅仅是反向处理。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;我们学到了什么&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;现在如果我需要一个经过用户验证的简单信息写操作，我会这么做：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;IMessageWriter msgWriter = new SecureMessageWriter(new MessageWriter());&lt;br/&gt;&lt;/div&gt;&lt;p&gt;我用&lt;span style="color: #993300;"&gt;SecureMessageWriter&lt;/span&gt;装饰了&lt;span style="color: #993300;"&gt;MessageWriter&lt;/span&gt;，它现在在写信息到磁盘前会先验证用户。如果同时需要验证用户和加密信息，我会这么做：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;IMessageWriter msgWriter = new SecureMessageWriter(new EncryptionMessageWriter(new MessageWriter()));&lt;br/&gt;&lt;/div&gt;&lt;ol&gt;&lt;li&gt;装饰器使我们在大多数情况下避免构造复杂基类，撰写大量的代码。&lt;/li&gt;&lt;li&gt;装饰器允许我们以不同的顺序进行不同的组合，这在别的方法来说不太容易。&lt;/li&gt;&lt;li&gt;相比为不同的行为与合并实现不同的基类，我们可以按需实现单独的需求行为。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;回到现实&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这一部分我们会看到装饰器模式在实际中应用的例子。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;同步包&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;善于使用.ET中旧集合类，如&lt;span style="color: #993300;"&gt;Queue&lt;/span&gt;，&lt;span style="color: #993300;"&gt;ArrayList&lt;/span&gt;等的人可能还记得许多类提供的(集合)同步函数。它把集合实例自己作为参数传入，并返回一个同步集合。尽管集合类自己并不同步，但这个方法返回的实际上是从集合类自己继承过来的一个装饰器。例如，在下面代码中当我们调用&lt;span style="color: #993300;"&gt;Syncrhonized(a1)&lt;/span&gt;时，我们会收到一个从&lt;span style="color: #993300;"&gt;ArrayList&lt;/span&gt;继承来的&lt;span style="color: #993300;"&gt;SyncArrayList&lt;/span&gt;的实例。 &lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt; ArrayList al = new ArrayList();&lt;br/&gt;al = ArrayList.Synchronized(al);&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="color: #993300;"&gt;SyncArrayList&lt;/span&gt;存储通过属性&lt;span style="color: #993300;"&gt;_list&lt;/span&gt;传递的&lt;span style="color: #993300;"&gt;ArrayList&lt;/span&gt;，并且按照同样的方法重载不同的实例方法。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt; public override int Add(object value) {&lt;br/&gt;        lock (this._root){&lt;br/&gt;            return this._list.Add(value);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="line-height: 17px; font-size: 12px; font-weight: bold;"&gt;注意事项&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;按照此法创建同步包时，要注意叫做&amp;ldquo;自死锁&amp;rdquo;现象，这意味着一个占有锁的线程进入另一格方法(或者递归)，然后又试图获取同一个对象的锁。在Windows中，如果你使用.NET实施监控，或者内核级命名，或者无名互斥，全部都有重入机制(即递归)。所以你不会遇到此类问题，但是在其他环境(如Linux)中编程时,默认互斥类型是快速互斥（一种非递归互斥），你的代码就可能成为&amp;ldquo;自死锁&amp;rdquo;的受害者。假如使用消息，即使在Windows上，它一样没有自我意识，如果你不注意，就会给你带来这个问题。当然，对于一个简单信号，比如n=1，在第二次访问时，你一样会遇到&amp;ldquo;自死锁&amp;rdquo;。&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;同理，你可以为你的集合类实现一个只读包。不像我们到现在所看到的，与其说他们是向类上添加功能，倒不如说去掉一些。例如在重载方法Add()中可能抛出操作不支持的异常。.NET提供了ReadOnlyCollection&amp;lt;T&amp;gt;，它用于包装泛型列表。Java则提供了只读包，如UnmodifiableCollection,UnmodifiableSet等等。&lt;/em&gt;&lt;br /&gt;Java中，你可以按照下面方式为很多集合类型获取同步包。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;List list = Collections.synchronizedList(new ArrayList());&lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="line-height: 17px; font-size: 12px; font-weight: bold;"&gt;Java和.NET中的IO&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Java的&lt;span style="color: #993300;"&gt;java.io&lt;/span&gt;包和.NET的&lt;span style="color: #993300;"&gt;Stream&lt;/span&gt;类都使用了该模式。我不会就它们的实现谈论很多细节。.NET中，&lt;span style="color: #993300;"&gt;Stream&lt;/span&gt;是一个抽象类，提供了基本的行为(如&lt;span style="color: #993300;"&gt;Component&lt;/span&gt;)，从抽象类&lt;span style="color: #993300;"&gt;Stream&lt;/span&gt;继承来的类&lt;span style="color: #993300;"&gt;FileStream&lt;/span&gt;,&lt;span style="color: #993300;"&gt;MemoryStream&lt;/span&gt;是&lt;span style="color: #993300;"&gt;ConcreteCompents&lt;/span&gt;，类&lt;span style="color: #993300;"&gt;BufferedStream&lt;/span&gt;,&lt;span style="color: #993300;"&gt;CrytoStream&lt;/span&gt;等是&lt;span style="color: #993300;"&gt;ConcreteDecorators&lt;/span&gt;。你能清楚地认识到它们同样忽略了&lt;span style="color: #993300;"&gt;Decorator&lt;/span&gt;。&lt;/p&gt;&lt;p&gt;同样，在Java中，&lt;span style="color: #993300;"&gt;BufferedReader&lt;/span&gt;和&lt;span style="color: #993300;"&gt;FilterReader&lt;/span&gt;是&lt;span style="color: #993300;"&gt;Reader&lt;/span&gt;的装饰者。而&lt;span style="color: #993300;"&gt;BufferedReader&lt;/span&gt;进一步被&lt;span style="color: #993300;"&gt;LineNumberReader&lt;/span&gt;装饰。&lt;span style="color: #993300;"&gt;FilterReader&lt;/span&gt;被&lt;span style="color: #993300;"&gt;PushbackReader&lt;/span&gt;装饰。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;收获了什么&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;装饰器模式允许我们在实现中提供扩展点。你可能注意到，在实现装饰者时，我从来没有涉及到&lt;span style="color: #993300;"&gt;Component&lt;/span&gt;类。因此，即使它并不拥有类，一样能通过动态添加行为类装饰它，甚至是递归的方式。这些额外的行为可能在几处行为之前或之后添加，或者这种行为可能被阻止。装饰者能在类中提供新方法，甚至新属性。但装饰器同样有一些问题。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;使用装饰器的程序员必须明白它们的意图，否则他最终可能会使用一些毫无意义的组合或序列。比如在我们的场景中，如果程序员按照这种方式定义序列：信息先被压缩，然后加密，最后验证，它将毫无意义。在现实场景中，有些组合或次序可能是灾难性的。&lt;/li&gt;&lt;li&gt;测试一个装饰类需要提供一个模拟的被装饰类。因为我们还没有涉及到测试，所以这里就不说了。&lt;/li&gt;&lt;li&gt;该模式在基本行为上添加一些职责。虽然给装饰者添加新的属性或方法完全合法，但这种方法导致基础类处理问题的灵活性，因为你需要用到具体的实例。&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;p&gt;&lt;strong&gt;写在最后&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;此文为&lt;a href="http://www.codeproject.com/"&gt;CodeProject&lt;/a&gt;上同名文章&amp;lt;&lt;a href="http://www.codeproject.com/KB/architecture/DecoratorPrimerA.aspx"&gt;Decorator Pattern(A Layman to Laymen)&lt;/a&gt;&lt;span&gt;&amp;gt;的意译和修改&lt;/span&gt;&lt;span&gt;，文中部分内容与原文有出入。&lt;strong&gt;文章通过循序渐进的方式逐步暴露问题(各种继承，子类，代码像麻花一样挤在一起)，然后用装饰模式解决(把每种需求单独构建成组件，然后像搭积木一样完成工作)，最后联系实际说明装饰模式的真正含义&lt;/strong&gt;，使得整篇文章有理有据，内容清晰易懂，相信对学习什么模式的人有很大帮助。限于个人能力，文中难免有错误的地方，还请大家多多指教（&lt;strong&gt;特别是斜体部分:(&lt;/strong&gt;）。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;本文参考：《设计模式可复用面向对象软件的基础》&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;　《&lt;a href="http://www.codeproject.com/KB/architecture/DecoratorPrimerA.aspx"&gt;Decorator Pattern(A Layman to Laymen)&lt;/a&gt;》&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;　《.NET与设计模式》&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;《MSDN》&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/niyw/aggbug/1847253.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/niyw/archive/2010/10/10/1847253.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/niyw/archive/2010/10/07/1845232.html</id><title type="text">C#中的委托,匿名方法和Lambda表达式</title><summary type="text">本文通过导向示例解释了创建委托的不同方法。</summary><published>2010-10-07T14:06:00Z</published><updated>2010-10-07T14:06:00Z</updated><author><name>倪大虾</name><uri>http://www.cnblogs.com/niyw/</uri></author><link rel="alternate" href="http://www.cnblogs.com/niyw/archive/2010/10/07/1845232.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/niyw/archive/2010/10/07/1845232.html"/><content type="html">&lt;p&gt;&lt;strong&gt;简介&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在.NET中，委托，匿名方法和Lambda表达式很容易发生混淆。我想下面的代码能证实这点。下面哪一个First会被编译？哪一个会返回我们需要的结果？即Customer.ID=5.答案是6个First不仅被编译，并都获得正确答案，且他们的结果一样。如果你对此感到困惑，那么请继续看这篇文章。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;class Customer &lt;br/&gt;{ &lt;br/&gt;    public int ID { get; set; } &lt;br/&gt;    public static bool Test(Customer x) &lt;br/&gt;    { &lt;br/&gt;        return x.ID == 5; &lt;br/&gt;    } &lt;br/&gt;} &lt;br/&gt;... &lt;br/&gt;List&amp;lt;Customer&amp;gt; custs = new List&amp;lt;Customer&amp;gt;(); &lt;br/&gt;custs.Add(new Customer() { ID = 1 }); &lt;br/&gt;custs.Add(new Customer() { ID = 5 }); &lt;br/&gt; &lt;br/&gt;custs.First(new Func&amp;lt;Customer, bool&amp;gt;(delegate(Customer x) { return x.ID == 5; })); &lt;br/&gt;custs.First(new Func&amp;lt;Customer, bool&amp;gt;((Customer x) =&amp;gt; x.ID == 5)); &lt;br/&gt;custs.First(delegate(Customer x) { return x.ID == 5; }); &lt;br/&gt;custs.First((Customer x) =&amp;gt; x.ID == 5); &lt;br/&gt;custs.First(x =&amp;gt; x.ID == 5); &lt;br/&gt;custs.First(Customer.Test); &lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="line-height: 31px; font-size: 21px; font-weight: bold;"&gt;什么是委托？&lt;/span&gt;&lt;/p&gt;&lt;p&gt;现在你定义一个处理用户订单的购物车ShoppingCart类。管理层决定根据数量，价格等给客人折扣。做为其中的一部分，他们已经实现了处理订单时你要考虑一方面。不用考虑过多，你简单声明一个变量来保存有&amp;ldquo;吸引力的折扣&amp;rdquo;(magicDisCount)，然后实现逻辑。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;class Program { &lt;br/&gt;    static void Main(string[] args)  { &lt;br/&gt;        new ShoppingCart().Process(); &lt;br/&gt;    } &lt;br/&gt;}  &lt;br/&gt;class ShoppingCart { &lt;br/&gt;    public void Process() { &lt;br/&gt;        int magicDiscount = 5; &lt;br/&gt;        // ... &lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;第二天，异想天开的管理层决定根据购买时间调整折扣。这个很简单，但需要你改动一点代码。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;class ShoppingCart { &lt;br/&gt;    public void Process() { &lt;br/&gt;        int magicDiscount = 5; &lt;br/&gt;        if (DateTime.Now.Hour &amp;lt; 12) { &lt;br/&gt;            magicDiscount = 10; &lt;br/&gt;        } &lt;br/&gt;    } &lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;接下来一段时间里，管理层又反复添加更多的折扣逻辑。这时你就会在心理抱怨&amp;ldquo;受够了&amp;rdquo;。那么我该怎么做才能把这些无聊的逻辑从我的代码中剥离出去，让该处理的人去处理呢？这时你要做的是移交或者委派给相应职能的别人。幸运的是，.NET为此提供了一种叫做&amp;ldquo;委托&amp;rdquo;的机制。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;委托&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果你有C/C++编程背景，描述委托最好的方法是&amp;ldquo;函数指针&amp;rdquo;。对所有人来说，可以认为把委托传递给方法与把值或对象传递给方法一样。比如下面三行代码就表现出一样的基本原则：你在传递数据给Process处理而不是你自己使用。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;// 给方法Process传递一个整形值&lt;br/&gt;Process( 5 ); &lt;br/&gt;// 给方法Process传递一个ArrayList的引用&lt;br/&gt;Process( new ArrayList() ); &lt;br/&gt;// 给方法Process传递一个方法的引用&lt;br/&gt;Process( discountDelegate );&lt;br/&gt;&lt;/div&gt;&lt;p&gt;DiscountDelegate是什么？我如何创建？Process方法如何使用？首先如同声明一个类一样，声明一个委托类型。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;delegate int DiscountDelegate(); &lt;br/&gt;&lt;/div&gt;&lt;span style="font-family: verdana, 'courier new'; line-height: 21px; white-space: normal; font-size: 14px;"&gt;这句话的意思是我们有一个叫DiscountDelegate的委托类型，我们可以像使用类，结构体等一样使用它。它不需要数据参数，但返回一个整数值。像类一样，我们必须创建一个它的实例它才有意义。记住，创建一个委托实例实质上是创建一个方法的引用。创建实例时关键是要明白DiscountDelegate没有任何构造器，它有一个隐式的构造函数来构造一个与它相同签名的方法(没有传入参数，返回一个整数)。那你怎么给这个构造函数一个方法呢？.NET向你提供了一个向它名字一样简单的方法，你所做的只是忽略圆括号。&lt;/span&gt;&lt;span style="font-family: verdana, 'courier new'; line-height: 21px; white-space: normal; font-size: 14px;"&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;pre class="brush:csharp"&gt;DiscountDelegate discount = new DiscountDelegate(class.method); &lt;br/&gt;&lt;/div&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-family: verdana, 'courier new'; line-height: 21px; white-space: normal; font-size: 14px;"&gt;在深入之前，先回到开始的例子，整理一个代码。我们会添加一个Calculator类来帮助我们处理折扣逻辑，并给我们的委托提供一些方法。&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;pre class="brush:csharp"&gt;delegate int DiscountDelegate(); &lt;br/&gt; &lt;br/&gt;class Program { &lt;br/&gt;    static void Main(string[] args) { &lt;br/&gt;        Calculator calc = new Calculator(); &lt;br/&gt;        DiscountDelegate discount = null; &lt;br/&gt;        if (DateTime.Now.Hour &amp;lt; 12) { &lt;br/&gt;            discount = new DiscountDelegate(calc.Morning); &lt;br/&gt;        } &lt;br/&gt;        else if (DateTime.Now.Hour &amp;lt; 20) { &lt;br/&gt;            discount = new DiscountDelegate(calc.Afternoon); &lt;br/&gt;        } &lt;br/&gt;        else { &lt;br/&gt;            discount = new DiscountDelegate(calc.Night); &lt;br/&gt;        } &lt;br/&gt;        new ShoppingCart().Process(discount); &lt;br/&gt;    } &lt;br/&gt;}  &lt;br/&gt;class Calculator { &lt;br/&gt;    public int Morning() { &lt;br/&gt;        return 5; &lt;br/&gt;    } &lt;br/&gt;    public int Afternoon() { &lt;br/&gt;        return 10; &lt;br/&gt;    } &lt;br/&gt;    public int Night() { &lt;br/&gt;        return 15; &lt;br/&gt;    } &lt;br/&gt;}  &lt;br/&gt;class ShoppingCart { &lt;br/&gt;    public void Process(DiscountDelegate discount) { &lt;br/&gt;        int magicDiscount = discount(); &lt;br/&gt;        // ... &lt;br/&gt;    } &lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-family: verdana, 'courier new'; line-height: 21px; white-space: normal; font-size: 14px;"&gt;&lt;p&gt;正如你所见，在Calculator类中，我们为每个逻辑分支创建了一个方法。在Main方法中，我们创建一个Calculator实例和一个DiscountDelegate实例，并按照我们所期望的把它们整合在一起。&lt;/p&gt;&lt;p&gt;太棒了，我们不用担心Process方法中的逻辑了，我们只需要简单得回调我们定义的委托。记住！我们不关心委托是如何创建的(或什么时间)，我们就像调用其他方法一样调用它。如你所见，另一种理解委托的方法是，它延迟执行一个方法。Calculator方法在过去某个时间本选择，但不会执行，直到我们调用discount()的时候。现在看看我们的解决方案，这里仍然存在一些丑陋的代码。在Calculator类中，我们可以用一个不同的方法来返回替代每个有返回值得方法吗？答案是肯定的，让我们把这些乱糟糟的代码合并起来。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;pre class="brush:csharp"&gt;delegate int DiscountDelegate(); &lt;br/&gt; &lt;br/&gt;class Program { &lt;br/&gt;    static void Main(string[] args) { &lt;br/&gt;        new ShoppingCart().Process(new DiscountDelegate(Calculator.Calculate)); &lt;br/&gt;    } &lt;br/&gt;}  &lt;br/&gt;class Calculator { &lt;br/&gt;    public static int Calculate() { &lt;br/&gt;        int discount = 0; &lt;br/&gt;        if (DateTime.Now.Hour &amp;lt; 12) { &lt;br/&gt;            discount = 5; &lt;br/&gt;        } &lt;br/&gt;        else if (DateTime.Now.Hour &amp;lt; 20) { &lt;br/&gt;            discount = 10; &lt;br/&gt;        } &lt;br/&gt;        else { &lt;br/&gt;            discount = 15; &lt;br/&gt;        } &lt;br/&gt;        return discount; &lt;br/&gt;    } &lt;br/&gt;}  &lt;br/&gt;class ShoppingCart { &lt;br/&gt;    public void Process(DiscountDelegate discount) { &lt;br/&gt;        int magicDiscount = discount(); &lt;br/&gt;         // ... &lt;br/&gt;    } &lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;这样子看起来更好点。你会注意到我们用一个静态的Calculate方法替换了所有原来的方法，在Main方法中也不用费心维护一个指向DiscountDelegate的引用。现在你明白了所有关于委托的东西了吗？在2004年.NET1.1中可以这么说，但是很不幸的是，这种框架自那以后更加成熟了。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;灯光，镜头，开始 或者我们需要Func!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;微软在.NET 2.0中引入了泛型，并提供了一个泛型委托:Action&amp;lt;T&amp;gt;。老实说，我认为它远不够用。后来在.NET 3.5中，它为我们提供了一些我们不想定义的通用委托。他们扩展了Action，并添加了Func，二者唯一区别在于Func型方法有一个返回值而Action型方法没有。&lt;/p&gt;&lt;p&gt;这意味着我们不需要声明自己的DiscountDelegate，可以用Func&amp;lt;int&amp;gt;替代。为说明这些观点是如何工作的，我们来假设管理层又一次改变了我们的逻辑，我们需要提供一些特殊的折扣。很简单，我们将给Calculate方法传入一个bool型值。&lt;/p&gt;&lt;p&gt;现在我们的委托签名变成Func&amp;lt;bool,int&amp;gt;。注意Calculate方法现在包含一个bool型参数，我们用一个bool值调用discount()。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;class Program { &lt;br/&gt;    static void Main(string[] args) { &lt;br/&gt;        new ShoppingCart().Process(new Func&amp;lt;bool, int&amp;gt;(Calculator.Calculate)); &lt;br/&gt;    } &lt;br/&gt;} &lt;br/&gt; &lt;br/&gt;class Calculator { &lt;br/&gt;    public static int Calculate(bool special) { &lt;br/&gt;        int discount = 0; &lt;br/&gt;        if (DateTime.Now.Hour &amp;lt; 12) { &lt;br/&gt;            discount = 5; &lt;br/&gt;        } &lt;br/&gt;        else if (DateTime.Now.Hour &amp;lt; 20) { &lt;br/&gt;            discount = 10; &lt;br/&gt;        } &lt;br/&gt;        else if (special) { &lt;br/&gt;            discount = 20; &lt;br/&gt;        } &lt;br/&gt;        else { &lt;br/&gt;            discount = 15; &lt;br/&gt;        } &lt;br/&gt;        return discount; &lt;br/&gt;    } &lt;br/&gt;} &lt;br/&gt; &lt;br/&gt;class ShoppingCart { &lt;br/&gt;    public void Process(Func&amp;lt;bool,int&amp;gt; discount) { &lt;br/&gt;        int magicDiscount = discount(false); &lt;br/&gt;        int magicDiscount2 = discount(true); &lt;br/&gt;    } &lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;好像还算不错，我们又省了一行代码，这样算结束了吗？当然没有，我们甚至能省掉类型判断。只要我们传递的方法有严格签名的委托，.NET允许我们完全忽略掉显式创建Func&amp;lt;bool,int&amp;gt;。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;//因为Process期望的方法有一个bool型输入参数和返回一个int值，所以下面这句话是正确的&lt;br/&gt;new ShoppingCart().Process(Calculator.Calculate); &lt;br/&gt;&lt;/div&gt;&lt;p&gt;至此，首先通过忽略自定义委托，我们省略了代码；然后排出了明确的创建Func委托。我们能继续压缩代码行吗？到此我们才完成此文的一半，答案显然是&amp;ldquo;能&amp;rdquo;。&lt;/p&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-family: verdana, 'courier new'; line-height: 21px; white-space: normal; font-size: 14px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: verdana, 'courier new'; line-height: 21px; white-space: normal; font-size: 21px; font-weight: bold;"&gt;匿名方法&lt;/span&gt;&lt;span style="font-family: verdana, 'courier new'; line-height: 21px; white-space: normal; font-size: 14px;"&gt;&lt;p&gt;匿名方法能够让你声明一个方法体而不需要给它指定一个名字。在接下来的场景里，它们以一个&amp;ldquo;普通的&amp;rdquo;方法存在；但是在你的代码中没有任何方法显式调用它。匿名方法只能在使用委托的时候创建，事实上，它们通过delegate关键字创建。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;&lt;pre class="brush:csharp"&gt;class Program { &lt;br/&gt;    static void Main(string[] args)     { &lt;br/&gt;        new ShoppingCart().Process( &lt;br/&gt;            new Func&amp;lt;bool, int&amp;gt;(delegate(bool x) { return x ? 10 : 5; } &lt;br/&gt;        )); &lt;br/&gt;    } &lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;正如你所见，我们完全删除了Calculator类的需求。你可以在打括号中添加任何其他方法中的逻辑。如果你在看它如何执行时有困难，那就把delegate(bool x)做为一个方法签名，而不是一个关键字。设想这段代码在一个类里，delegate(bool x){return 5;}是一个完整的合法方法声明(我们确实有一个返回值)，恰好delegate是一个保留字，在这里，它让这个方法匿名。&lt;/p&gt;&lt;p&gt;至此，我确信现在你知道这里我们甚至能压缩更多的代码。顺利成章的，我们能忽略显式声明Func委托的需要；.NET让我们使用delegate关键字更方便。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;class Program { &lt;br/&gt;    static void Main(string[] args) { &lt;br/&gt;        new ShoppingCart().Process( &lt;br/&gt;          delegate(bool x) { return x ? 10 : 5; } &lt;br/&gt;        ); &lt;br/&gt;    } &lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;当把.NET方法做为委托参数时或处理时间时，就能看到匿名方法的真正用处。之前，你会为你所关注的所有可能行为创建了一个方法，现在你仅需以内联的方式创建它们，并可以避免污染你的命名空间。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;// 创建一个匿名比对方法&lt;br/&gt;custs.Sort(delegate(Customer c1, Customer c2) { &lt;br/&gt;    return Comparer&amp;lt;int&amp;gt;.Default.Compare(c1.ID, c2.ID); &lt;br/&gt;}); &lt;br/&gt; &lt;br/&gt;//  创建一个匿名事件&lt;br/&gt;button1.Click += delegate(object o, EventArgs e) { MessageBox.Show("Click!"); }; &lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="font-size: 21px; font-weight: bold;"&gt;Lambda 表达式&lt;/span&gt;&lt;/p&gt;&lt;p&gt;MSDN中写道：&amp;ldquo;Lambda 表达式&amp;rdquo;是一个匿名函数，它可以包含表达式和语句，并且可用于创建委托或表达式树类型。你应当明白&amp;ldquo;用户创建委托&amp;rdquo;部分，但什么是&amp;ldquo;表达式&amp;rdquo;呢？老实说，表达式和表达式树不在此为讨论范围内。现在我们唯一需要明白的是，表达式是.NET程序运行时表示数据或对象的代码(C#代码)。引用Jon Skeet的话：&amp;ldquo;&lt;span&gt;表达式树是一种表达逻辑，这样其他的代码可以查询的方法。&lt;/span&gt;&lt;span&gt;当一个lambda表达式转换成一个表达式树，编译器不会发出了lambda表达式的白细胞介素，它会发出白细胞介素这将会建立一个表达式树表示相同的逻辑。&lt;/span&gt;&amp;rdquo;&lt;/p&gt;&lt;p&gt;我们需要关注的是Lambda表达式替换匿名方法，和其他的特性。回顾我们最后例子，我们已经在一行代码里压缩了处理整个折扣算法的逻辑。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;class Program { &lt;br/&gt;    static void Main(string[] args) { &lt;br/&gt;        new ShoppingCart().Process( &lt;br/&gt;            delegate(bool x) { return x ? 10 : 5; } &lt;br/&gt;        ); &lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;你相信我们能让这个更短吗？Lambda表达式用'=&amp;gt;'运算符表明什么参数传递给表达式。编译器进一步处理，允许我们忽略类型并自动替我们推断这些类型。如果你有2个或更多个参数，你需要用圆括号:(x,y)=&amp;gt;。如果只有一个，你设置不需要这样：x=&amp;gt;。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;static void Main(string[] args) { &lt;br/&gt;    Func&amp;lt;bool, int&amp;gt; del = x =&amp;gt; x ? 10 : 5; &lt;br/&gt;    new ShoppingCart().Process(del); &lt;br/&gt;} &lt;br/&gt;// 更短啦...&lt;br/&gt;static void Main(string[] args) { &lt;br/&gt;    new ShoppingCart().Process(x =&amp;gt; x ? 10 : 5); &lt;br/&gt;}&lt;br/&gt;&lt;/div&gt;&lt;p&gt;就是这样子。x被推断为bool型，并且有返回值，因为Process接收一个Func&amp;lt;bool,int&amp;gt;。如果我们想实现像之前那样的完整代码块，我们只需要加上大括号。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;static void Main(string[] args) { &lt;br/&gt;    new ShoppingCart().Process(  x =&amp;gt; { &lt;br/&gt;        int discount = 0; &lt;br/&gt;        if (DateTime.Now.Hour &amp;lt; 12) { &lt;br/&gt;            discount = 5; &lt;br/&gt;        } &lt;br/&gt;        else if (DateTime.Now.Hour &amp;lt; 20) { &lt;br/&gt;            discount = 10; &lt;br/&gt;        } &lt;br/&gt;        else if(x)  { &lt;br/&gt;            discount = 20; &lt;br/&gt;        } &lt;br/&gt;        else { &lt;br/&gt;             discount = 15; &lt;br/&gt;        } &lt;br/&gt;        return discount; &lt;br/&gt;    }); &lt;br/&gt;} &lt;br/&gt;&lt;/div&gt;&lt;p&gt;&lt;span style="font-size: 21px; font-weight: bold;"&gt;写在最后&lt;/span&gt;&lt;/p&gt;&lt;p&gt;使用与不使用大括号有一个重要的不同。当你用时，你创建一个&amp;ldquo;语句Lambda&amp;rdquo;，反之，它是"表达Lambda"。语句Lambda能执行多条语句(因此需要大括号)，但不能创建表达树。你可能只在使用IQueryable接口是遇到这个问题。下面的例子说明这个问题。&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"&gt;List&amp;lt;string&amp;gt; list = new List&amp;lt;string&amp;gt;(); &lt;br/&gt;IQueryable&amp;lt;string&amp;gt; query = list.AsQueryable(); &lt;br/&gt;list.Add("one"); &lt;br/&gt;list.Add("two"); &lt;br/&gt;list.Add("three"); &lt;br/&gt; &lt;br/&gt;string foo = list.First(x =&amp;gt; x.EndsWith("o")); &lt;br/&gt;string bar = query.First(x =&amp;gt; x.EndsWith("o")); &lt;br/&gt;// foo and bar are now both 'two' as expected &lt;br/&gt;foo = list.First(x =&amp;gt; { return x.EndsWith("e"); }); //no error &lt;br/&gt;bar = query.First(x =&amp;gt; { return x.EndsWith("e"); }); //error &lt;br/&gt;bar = query.First((Func&amp;lt;string,bool&amp;gt;)(x =&amp;gt; { return x.EndsWith("e"); })); //no error &lt;br/&gt;&lt;/div&gt;&lt;p&gt;倒数第二行在编译时失败。这是因为IQueryable.First期望得到一个表达式作为参数，然而List&amp;lt;T&amp;gt;.First期望得到一个委托。你可以按照最后一行强制转换Lambda到一个委托(使用First的方法重载)。&lt;/p&gt;&lt;p&gt;这里很难结束讨论，但是我觉得必须停止。Lambda大体上分为两类：一类创建匿名方法和委托；另一类创建表达式。表达式自成一体，并不是.NET开发者的必备知识(无疑在LINQ中已有实现)。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;em&gt;备注：&lt;/em&gt;&lt;/p&gt;&lt;p&gt;此文为&lt;a href="http://www.codeproject.com/"&gt;CodeProject&lt;/a&gt;上的同名文章&amp;lt;&lt;span&gt;&lt;a href="http://www.codeproject.com/KB/cs/DelegatesOMy.aspx"&gt;C# Delegates,Anonymous Methods, and Lambda Expressions&lt;/a&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;，个人觉得非常好，所以就翻一下给不想看英文的同学。由于能力有限，翻译的不好，望大家多多包涵。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;/span&gt;&lt;/pre&gt;&lt;img src="http://www.cnblogs.com/niyw/aggbug/1845232.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/niyw/archive/2010/10/07/1845232.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/niyw/archive/2010/09/25/1834859.html</id><title type="text">[讨论]未来有哪些编程概念会消失?</title><summary type="text">本文是个人对编程语言未来样貌的一点猜想，你可以认为是YY帖，也可以认为是科幻帖。本人目的主要是跟大家讨论一个轻松而又不失内容的话题，既供学习又供娱乐。</summary><published>2010-09-25T13:21:00Z</published><updated>2010-09-25T13:21:00Z</updated><author><name>倪大虾</name><uri>http://www.cnblogs.com/niyw/</uri></author><link rel="alternate" href="http://www.cnblogs.com/niyw/archive/2010/09/25/1834859.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/niyw/archive/2010/09/25/1834859.html"/><content type="html">&lt;p&gt;今天重新看C#中委托，匿名方法等概念，脑子里突然冒出这么一个想法：未来高级语言编程会是什么样子，有哪些东西我们不用关心，现在拿出来给大家讨论一下。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;我这里所说的高级语言是指最早的面向对象语言C++,Pascal等，后来的Smalltalk等，以及现代语言C#和Java，直到今天最新C# 4.0。注意：这里有2个C#，我没有写错，理由稍后再说。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;大家知道，C++是从C扩展而来，所以它既支持面向过程，也支持面向对象。作为最早出现的面向对象高级语言，在今天还有很重要的地位。但任何编程的人都会为C++及以往语言中指针头痛不已。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;随后出现了Smalltalk等纯面向对象语言，这个不了解，一笔带过。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;20世纪90年代，出现了Java。Java的出现可谓竞艳四方，以至于以后N年稳坐排行榜首位。我想，之所以有这样的结果，最重要的就是Java中没有了指针，让程序员彻底从错综复杂的指针中解脱出来，大大提升了开发效率。这时候第一个与今天主题有关的概念出现了&amp;mdash;&amp;mdash;&lt;strong&gt;指针消失&lt;/strong&gt;。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Java之后不久就有了C#。最早的C#既有Delphi的优良血统，又到处包含Java的影子。不过初生的C#显得过于稚嫩，直到2.0才完成成熟。个人认为C#是非常优秀的现代编程语言，但它还在传统面向对象的范围内。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;最近几年，相对于Java的老态龙钟，蹒跚不前，C#一直蓬勃发展，先后经历了3.0，3.5，直到最新的4.0版本。此时，我们惊奇的发现C#中多了诸如Lambda表达式，LinQ，动态编程，无类型等非传统面向对象，甚至是破坏面向对象的元素。而这些元素或多或少的都让我们的开发效率有所提升，也使得C# 4.0与2.0隐隐有巨大的不同。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;再考虑到&lt;strong&gt;近年来不断涌现的各种编程技术和思想&lt;/strong&gt;，比如SOA，AOP，CMS等等，渐渐的我们发现，我们&lt;strong&gt;正在离传统编程中关注的概念越来越远，甚至可以不用考虑&lt;/strong&gt;。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;现在看来，这些传统的概念包括指针，&lt;strong&gt;基本数据类型，操作符，多线程&lt;/strong&gt;等。&lt;strong&gt;指针在Java，C#语言中已经消失&lt;/strong&gt;，那么下一个消失的特性会是哪一个呢？我想可能会是基本数据类型，也可能是操作符，更有可能是多线程。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;基本数据类型&lt;/strong&gt;：基本数据类型之所以会消失，并不是想指针一样用不着，而是不会像现在一样用的那么频繁。比如也许有一天，我们不用声明一个Person的类，里面包含一个表示年龄的Int字段。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;操作符&lt;/strong&gt;：现代编程语言有很多的操作符，如一元运算符，二元运算符，三元运算符或者数值类，逻辑类等。这些操作符虽然提升了运算性能，但也带来的程序的复杂度，让程序员关注了更多不必要的内容。而未来这些可能消失，我们根本不用关心位运算，数值运算。这样子，程序员只用关系自己需要实现的业务逻辑就行了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;多线程&lt;/strong&gt;：多线程从出现，到今天，其学习和使用的代价已经减少了很多，而我认为这些进步还不够，因为我们还纠结在同步，异步，锁等乱七八糟的概念中，甚至还有并行计算。而这些与我们要解决的业务逻辑根本没有直接的关系。如果没有这些，相信我们的开发效率可以提升N倍，软件性能可以提升N倍。这是一个广所熟知的问题，所以未来有一天，多线程可能真的会消失。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;最后总结一下，文中所说的消失并不是真正意义上的消失，而是猜想未来有一天，基本数据类型，操作符，尤其是多线程/并行计算可能像今天的指针一样，有个如同GC一样的东西自动管理实现。以上纯属个人YY，也欢迎大家来拍转。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/niyw/aggbug/1834859.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/niyw/archive/2010/09/25/1834859.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
