﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-在路上-文章分类-Java设计模式</title><link>http://www.blogjava.net/totobacoo/category/25051.html</link><description>姿势就是力量</description><language>zh-cn</language><lastBuildDate>Tue, 21 Aug 2007 16:53:49 GMT</lastBuildDate><pubDate>Tue, 21 Aug 2007 16:53:49 GMT</pubDate><ttl>60</ttl><item><title>《JAVA与模式》重读心得和笔记 &lt;一. 设计原则简言&gt;</title><link>http://www.blogjava.net/totobacoo/articles/138227.html</link><dc:creator>Samuel.Mo</dc:creator><author>Samuel.Mo</author><pubDate>Mon, 20 Aug 2007 13:02:00 GMT</pubDate><guid>http://www.blogjava.net/totobacoo/articles/138227.html</guid><wfw:comment>http://www.blogjava.net/totobacoo/comments/138227.html</wfw:comment><comments>http://www.blogjava.net/totobacoo/articles/138227.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/totobacoo/comments/commentRss/138227.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/totobacoo/services/trackbacks/138227.html</trackback:ping><description><![CDATA[<p><br><strong>一、开闭原则</strong></p>
<p>一个软件实体应当对扩展开放，对修改关闭。 <br>原文：Software entities should be open for extension, but closed for modification. <br>引自：Bertrand Meyer[MEYER88]</p>
<p>这个原则说的是，在设计一个模块的时候，应当使这个模块可以在不被修改的前提下被扩展。<br>换言之，应当可以在不必修改源代码的情况下改变这个模块的行为。</p>
<p>用面向对象的语言来讲，不允许修改的是系统的抽象层，而允许扩展的是系统的实现层。</p>
<p><br><br><strong>二、里氏代换原则（LSP）</strong></p>
<p>如果对每一个类型为 T1 的对象 o1，都有类型为 T2 的对象 o2，使得以 T1 定义的所有程序 P<br>在所有的对象 o1 都被代换成 o2 时，程序 P 的行为没有变化，那么类型 T2 是类型 T1 的子类型。</p>
<p>换言之，一个软件实体如果使用的是一个基类的话，那么一定适用于其子类，而且它根本不能察觉出<br>基类对象和子类对象的区别。</p>
<p>里氏代换原则是继承复用的基石。只有当衍生类可以替换掉基类，软件单位的功能不会收到影响时，<br>基类才能真正被复用，而衍生类也才能够在基类的基础上增加新的行为。</p>
<p>反过来的代换是不成立的。即如果一个软件实体使用的是一个子类的话，那么它不一定使用于基类。<br>比如，Base 是 Derived 的基类。有一个方法 method1 接受子类对象为参数：<br>method1(Derived d)<br>那么一般而已不可以有 method1(b)。 注：b 为 Base 类的实例</p>
<p><br><br><br><strong>三、依赖倒转原则（Dependence Inversion）</strong></p>
<p>依赖倒转原则讲的是：要依赖于抽象，不要依赖于具体。</p>
<p><br>传统的过程性系统的设计办法倾向于使高层次的模块依赖于低层次的模块；抽象层次依赖于具体层次。<br>依赖倒转原则是要把这个错的依赖关系倒转过来，这就是&#8220;依赖倒转原则&#8221;的来由。</p>
<p>通常，依赖（耦合）关系分为三种：</p>
<p>1. 零耦合（Nil Coupling）关系：两个类之间没有耦合关系。</p>
<p>2. 具体耦合（Concrete Coupling）关系：具体性耦合发生在两个具体的（可实例化的）类直接，经由<br>一个类对另一个具体类的直接引用造成。</p>
<p>3. 抽象耦合（Abstract Coupling）关系：抽象耦合关系发生在一个具体类和一个抽象类（或者java接口）<br>之间，使两个必须发生关系的类之间存有最大的灵活性。</p>
<p>依赖倒转原则要求客户端依赖于抽象耦合。他的另一种表述是：要针对接口编程、不要针对实现编程。</p>
<p>通常，实现依赖倒转原则的手段是：工厂方法模式、模板方法模式、迭代子模式（这也是 Collection 类型<br>在可以通过 for 、while 方式遍历的情况下，还提供 iterator 遍历方法供调用方使用的原因）。</p>
<p><br><br><br><strong>四、接口隔离原则（Interface Segregation）</strong></p>
<p>接口隔离原则讲的是：使用多个专门的接口比使用单一的总接口要好。 换言之，从一个客户类的角度来讲：<br>一个类对另外一个类的依赖性应当是建立在最小的接口上的。</p>
<p>由于每一个接口都代表一个角色，实现一个接口的对象，在他的整个生命周期中都扮演这个角色。因此将<br>角色划分清楚是系统设计的一个重要工作。因此，一个符合逻辑的推断，不应当</p>
<p>将几个不同的角色都交给同一个接口，而应当交给不同的接口。</p>
<p>过于臃肿的接口是对接口的污染（Interface Contamination）。</p>
<p><br><br><br><strong>五、合成/聚合复用原则（Composite/Aggregate Reuse）</strong></p>
<p>合成/聚合复用原则（CARP）经常又叫合成复用原则（CRP）。合成/聚合复用就是在一个新的对象里面使用一些<br>已有的对象，使之成为新对象的一部分；新的对象通过向这些对象的委派达到复用已有功能的目的。这个设计<br>原则有另一个更简短的表述：要尽量使用合成/聚合，尽量不要使用继承。</p>
<p>Java API 中，有几个明显违反这一原则的例子，其中最为著名的就是 Stack 和 Properties。前者被不当地设置<br>为 Vector 的子类，而 Properties 被不恰当地设置成 Hashtable 的子类。</p>
<p>一个 Stack 不是一个 Vector（NOT IS-A），所以 Stack 不应当设置成为 Vector 的子类。同样地，一个 Properties<br>也不是一个 Hashtable。 在这两种情况下，使用聚合比使用继承关系更合适。</p>
<p>由于 Properties 继承了 Hashtable 的行为，因而当 p 是一个 Properties 类型的对象是，p.getProperties(key)<br>与 p.get(key) 就会给出不同的结果。前者来自于 Properties 本身，因此会利用默认值；而后者则来自于 Hashtable，<br>因此不会使用默认值。</p>
<p>更糟糕的是，由于 Properties 是 Hashtable 的子类，因此，客户端可以通过类型的转换，直接使用超类的行为。<br>比如，Properties 假定所有的键和值都是 String 类型的，如果不是，就会导致运行崩溃。但是，客户端完全可以<br>通过 Hashtable 提供的行为加入任意类型的键和值，绕过 Properties 的接口，并导致 Properties 的内部矛盾和<br>崩溃。</p>
<p>这样说来，Properties 其实仅仅是有一些 Hashtable 的属性的，换言之，这是一个 "Has-A" 的关系，而不是一个<br>"Is-A" 的关系。</p>
<p><br><br><br><strong>六、迪米特法则（LoD）</strong></p>
<p>迪米特法则（Law of Demeter）又叫做最少知识原则（Least Knowledge Principle），就是说，一个对象应当对其他<br>对象有尽可能少的了解。</p>
<p>迪米特法则最初是用来作为面向对象的系统设计风格的一种法则，这条法则实际上是很多著名系统，比如火星登录软件<br>系统、木星的欧罗巴卫星轨道飞船的软件系统的指导设计原则。</p>
<p>关于迪米特法则，比较有代表性的几种描述如下：</p>
<p>1. 只与你直接的朋友们通信（Only talk to your immediate friends）</p>
<p>2. 不要跟&#8220;陌生人&#8221;说话（Don't talk to strangers）</p>
<p>3. 每一个软件单位对其他的单位都只有最少的知识，而且局限于那些与本单位密切相关的软件单位。</p>
<p><br>迪米特法则的主要用意是控制信息的过载。在将迪米特法则运用到系统设计中时，要注意下面的几点：</p>
<p>1. 在类的划分上，应当创建有弱耦合的类。类之间的耦合越弱，就越有利于复用。一个处在弱耦合中的类一旦被修改，<br>不会对有关系的类造成波及。</p>
<p>2. 在类的结构设计上，每一个类都应当尽量降低成员的访问权限（Accessibility）。换言之，一个类包装好各自的<br>private 状态（自己的&#8220;秘密&#8221;）。 这样一来，想要了解其中的一个类的意义时，不需要了解很多别的类的细节。一个<br>类不应当 public 自己的属性，而应当提供取值和赋值方法让外界间接访问自己的属性。</p>
<p>3. 在类的设计上，只要有可能，一个类应当设计成不变类。</p>
<p>4. 在对其他类的引用上，一个对象对其对象的引用应当降到最低。</p>
<img src ="http://www.blogjava.net/totobacoo/aggbug/138227.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/totobacoo/" target="_blank">Samuel.Mo</a> 2007-08-20 21:02 <a href="http://www.blogjava.net/totobacoo/articles/138227.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《JAVA与模式》重读心得和笔记 &lt;一. 设计模式简言&gt;</title><link>http://www.blogjava.net/totobacoo/articles/137582.html</link><dc:creator>Samuel.Mo</dc:creator><author>Samuel.Mo</author><pubDate>Fri, 17 Aug 2007 08:22:00 GMT</pubDate><guid>http://www.blogjava.net/totobacoo/articles/137582.html</guid><wfw:comment>http://www.blogjava.net/totobacoo/comments/137582.html</wfw:comment><comments>http://www.blogjava.net/totobacoo/articles/137582.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/totobacoo/comments/commentRss/137582.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/totobacoo/services/trackbacks/137582.html</trackback:ping><description><![CDATA[<p><br>阎宏的《JAVA与模式》，本来已经在书堆里面尘封了。之前第一遍看过后，有些地方觉得比较抽象，也没细体会。 <br>一晃两年过去，偶然因为一个设计模式的疑惑，把它又找出来了（书很多，找得很辛苦）。重读这本书时，感觉理解<br>起来和两年前完全不同了，几十页一气呵成。很久没有这种读书的状态了。于是决定从头再读，读了还不算，顺便记点<br>笔记，贻笑大方。<br><br><br>一节，设计模式的一些基础概念。大概都是些老生常谈的东西，但缺少它，就不是完整的笔记了。所以题目叫简言。<br><br>&nbsp;=================================================================================<br><br><strong>Peter Coad 软件设计目标：</strong></p>
<p>1. 可扩展性（Extensibility）</p>
<p>新的功能可以很容易的加入到系统</p>
<p>2. 灵活性（Flexibility）</p>
<p>可以允许代码修改平稳地发生，而不会设计到很多其他的模块</p>
<p>3. 可插入性（Pluggability）</p>
<p>可以很容易地将一个类抽出去，同时将另一个有同样接口的类加入进来</p>
<p><br><strong>达成理想软件设计目标的关键是设计的抽象化。<br></strong></p>
<p>抽象化的基石：<strong>接口和抽象类</strong></p>
<p>一、接口 （Interface）</p>
<p>接口是实现构件的可插入性（Pluggability）的关键。</p>
<p>1. 接口保证关联的可插入性</p>
<p>通过接口，我们可以实现动态切换一个类到另一个类的关联关系。 比如 类A 关联了类 B，<br>如果需求更改，类 A 需要关联类 C，我们只有修改类A 的代码。 如果类B和类C行为相似，<br>那我们可以提炼出接口 E。类A 只需要关联到接口E，就可以在不修改代码的情况下，自由<br>切换类A与类B或者类C的关联关系。</p>
<p>2. 接口保证调用的可插入性</p>
<p>同样，一个对象不可避免地需要调用其他对象的方法。这种调用不一定非得是某一个具体类，<br>而可以是一个接口。这样一来，任何实现了这个接口的具体类都可以被当前对象调用；而当前<br>对象到底调用的是哪一个具体类的实例则完全可以动态地决定。</p>
<p>因此，接口提供了关联以及方法调用上的可插入性，软件系统的规模越大，生命周期越长，接口<br>的重要性就越大。接口使得软件系统在灵活性和可扩展性、可插入性方面得到保证。</p>
<p>&nbsp;</p>
<p>接口的分类：</p>
<p>1. 单方法接口。 如 Runnable</p>
<p>2. 标识接口。如 Serializable、java.rmi.Remote</p>
<p>3. 常量接口。 不推荐<br></p>
<p><br>&nbsp;</p>
<p>二、抽象类 （Abstract Class）</p>
<p>抽象类的重要设计原则：</p>
<p>1. 抽象类是用来继承的；具体类不是用来继承的</p>
<p>2. 抽象类应该拥有尽可能多的共同代码 （代码复用、节约内存资源）</p>
<p>3. 抽象类应该拥有尽可能少的数据 （节省内存资源）&nbsp;&nbsp;&nbsp;&nbsp;<br><br><br><br><strong>接口与抽象类的优缺比较：</strong> <br><br>1. 两者最大的区别，java 抽象类可以提供某些方法的部分实现，而java接口则不可以。<br><br>2. 子类只能继承一个抽象类，但可以实现多个接口。<br><br>3.&nbsp; 代码重构方面。将一个单独的java具体类重构成一个java接口的实现是很容易的，<br>&nbsp;&nbsp;&nbsp;&nbsp; 而为一个已有的具体类添加一个java抽象类作为抽象类型取不那么容易，因为这个<br>&nbsp;&nbsp;&nbsp;&nbsp; 具体类有可能已经有了一个超类。<br><br>4.&nbsp; java接口是定义混合类型（Mixin Type）的理想工具。所谓混合类型，就是在一个类<br>&nbsp;&nbsp;&nbsp; 的主类型之外的次要类型。一个混合类型表明一个类不仅仅具有某个主类型的行为，<br>&nbsp;&nbsp;&nbsp; 而且具有其他的次要行为。比如 Hashtable<br><br><br><strong>联合使用java接口和java抽象类：<br><br></strong>由于java抽象类具有提供缺省实现的优点，而java接口具有其他所有的优点。因此联合使用<br>两者就是一个很好的选择。<br><br>首先，声明类型的工作仍然是java接口承担的，但是同时给出的还有一个java抽象类，为这个<br>接口给出一个缺省实现。其他同属于这个抽象类型的具体类可以选择实现这个java接口，也可<br>以选择继承自这个抽象类。<br><br>这其实就是缺省适配模式（Default Adapter）。Java API 中也用了这种缺省适配模式，而且全都<br>遵循一定的命名规范:Abstract + 接口名。比如接口Collection，抽象类的名字是AbstractCollection。<br><br>这种联合使用接口和抽象类的做法，可以充分利用两者的优点，克服两者的缺点。<br></p>
<img src ="http://www.blogjava.net/totobacoo/aggbug/137582.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/totobacoo/" target="_blank">Samuel.Mo</a> 2007-08-17 16:22 <a href="http://www.blogjava.net/totobacoo/articles/137582.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>