1. 程式人生 > >Java設計模式——六大原則

Java設計模式——六大原則

推薦大家一本書:Android原始碼設計模式解析與實踐,本書從原始碼和實踐中帶你瞭解32種設計模式和設計模式的6大原則,我以讀完受益匪淺。

設計模式六大原則1:里氏置換原則

里氏置換原則(Liskov Substitution Principle),簡稱LSP。所有引用基類的地方必須能夠透明的使用其子類物件。也就是說,只要父類出現的地方子類就能夠出現,而且替換為子類不會產生任何錯誤或異常。

里氏置換原則(Liskov Substitution Principle),簡稱LSP
定義:
Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.
所有引用基類的地方必須能夠透明的使用其子類物件。
也就是說,只要父類出現的地方子類就能夠出現,而且替換為子類不會產生任何錯誤或異常。但是反過來,子類出現的地方,替換為父類就可能出現問題了。
這個原則是為良好的繼承定義一個規範,簡單的講,有4層含義:
一、子類必須完全實現父類的方法
定義一個抽象類
public abstract class ViewPoint {  
    //去麗江旅遊  
    public abstract void where();  

下面兩個類是實現這個抽象類
public class Lijiang extends ViewPoint {  
   
    @Override 
    public void where() {  
        System.out.println("歡迎來到麗江...");  
    }  
   
}  
 
public class Zhangjiajie extends ViewPoint {  
   
    @Override 
    public void where() {  
        System.out.println("歡迎來到張家界...");  
    }  
   

人物是塗塗,在裡面設定類型別來傳遞引數。此時塗塗要去的旅遊景點還是抽象的
public class Tutu {  
    //定義要旅遊的景點  
    private ViewPoint viewpoint;  
    //塗塗要去的景點  
    public void setViewPoint(ViewPoint viewpoint)  
    {  
        this.viewpoint = viewpoint;  
    }  
       
    public void travelTo()  
    {  
        System.out.println("塗塗要去旅遊了");  
        viewpoint.where();  
    }  

場景類。設定具體要去的景點
public class Sence {  
    public static void main(String args[])  
    {  
        Tutu tutu = new Tutu();  
        //設定要去的旅遊景點  
        tutu.setViewPoint(new Lijiang());  
        tutu.travelTo();  
    }  

執行結果:
塗塗要去旅遊了
歡迎來到麗江...
二、子類可以有自己的特性
也就是說在類的子類上,可以定義其他的方法或屬性
三、覆蓋或者實現父類的方法時輸入引數可以被放大
父類能夠存在的地方,子類就能存在,並且不會對執行結果有變動。反之則不行。
父類,say()裡面的引數是HashMap型別,是Map型別的子型別。(因為子類的範圍應該比父類大)
import java.util.Collection;  
import java.util.HashMap;  
   
public class Father {  
    public Collection say(HashMap map)  
    {  
        System.out.println("父類被執行...");  
        return map.values();  
    }  

子類,say()裡面的引數變成了Map型別,Map範圍比HashMap型別大,符合LSP原則。注意這裡的say不是覆寫父類的say,因為引數型別不同。而是過載。
import java.util.Collection;  
import java.util.Map;  
   
/*  
 * 子類繼承了父類的所有屬性  
 */ 
public class Son extends Father {  
    //方法輸入引數型別  
    public Collection say(Map map)  
    {  
        System.out.println("子類被執行...");  
        return map.values();  
    }  

場景類
import java.util.HashMap;  
   
public class Home {  
    public static void main(String args[])  
    {  
        invoke();  
    }  
       
    public static void invoke()  
    {  
        //父類存在的地方,子類就應該能夠存在  
        //Father f = new Father();  
        Son s = new Son();  
        HashMap map = new HashMap();  
        //f.say(map);  
        s.say(map);  
    }  

無論是用父類還是子類呼叫say方法,得到的結果都是
父類被執行...
但是,如果將上面Father裡的say引數改為Map,子類Son裡的say引數改為HashMap,得到的結果就變成了
f.say(map)結果:父類被執行...
s.say(map)結果: 子類被執行...
這樣會造成邏輯混亂。所以子類中方法的前置條件必須與父類中被覆寫的前置條件相同或者更寬。
四、覆寫或者實現父類的方法時輸出結果可以被縮小
其實與上面的類似,也就是父類能出現的地方子類就可以出現,而且替換為子類不會產生任何錯誤或者異常,使用者也無需知道是父類還是子類。但是反過來就不行了,有子類出現的地方,父類未必就適應。(畢竟子類的範圍要>=父類的範圍)

原文連結:http://www.cnblogs.com/loulijun/archive/2012/03/04/2379082.html

設計模式六大原則2:依賴倒置原則

而依賴倒置原則的本質騎士就是通過抽象(抽象類或介面)使各個類或模組的實現彼此獨立,不相互影響,實現模組間的鬆耦合。但是這個原則也是6個設計原則中最難以實現的了,如果沒有實現這個原則,那麼也就意味著開閉原則(對擴充套件開發,對修改關閉)也無法實現。

依賴倒置原則(Dependence Inversion Principle),簡稱DIP
定義
High level modules should depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.

1、高層模組不應該依賴低層模組,兩者都應該依賴於抽象(抽象類或介面)
2、抽象(抽象類或介面)不應該依賴於細節(具體實現類)
3、細節(具體實現類)應該依賴抽象
抽象:即抽象類或介面,兩者是不能夠例項化的。
細節:即具體的實現類,實現介面或者繼承抽象類所產生的類,兩者可以通過關鍵字new直接被例項化。
而依賴倒置原則的本質騎士就是通過抽象(抽象類或介面)使各個類或模組的實現彼此獨立,不相互影響,實現模組間的鬆耦合。但是這個原則也是6個設計原則中最難以實現的了,如果沒有實現這個原則,那麼也就意味著開閉原則(對擴充套件開發,對修改關閉)也無法實現。
依賴倒置有三種方式來實現
1、通過建構函式傳遞依賴物件
比如在建構函式中的需要傳遞的引數是抽象類或介面的方式實現。
2、通過setter方法傳遞依賴物件
即在我們設定的setXXX方法中的引數為抽象類或介面,來實現傳遞依賴物件
3、介面宣告實現依賴物件
例如下面的例子
塗塗是個女僧
public class Tutu {  
    //塗塗是個女孩,會煮麵  
    public void cook(Noodles noodles)  
    {  
        noodles.eat();  
    }  

麵條(目前只會煮麵)
public class Noodles {  
    //吃麵條  
    public void eat()  
    {  
        System.out.println("塗塗吃麵條...");  
    }  

塗塗坐在家裡吃麵(場景類)
public class Home {  
    public static void main(String args[])  
    {  
        Tutu tutu = new Tutu();  
        Noodles food = new Noodles();  
        tutu.cook(food);  
    }  

執行結果:塗塗吃麵條...
但是這有個問題,塗塗只會做麵條,不可能每次都吃麵條吧,天天吃麵吃死你,所以在上面的Tutu類中的cook方法中,如果塗塗會做其他吃的,那豈不是更好。於是她向家庭主婦邁進了一步,使用了依賴倒置原則。
也就是塗塗通過學習還可以燜米飯,炒魷魚(雖然聽著不爽,但是很好吃),京醬肉絲啊等等。要想在程式碼中實現,就需要實現兩個介面:ITutu和IFood
public interface ITutu {  
    //這樣就會做很多飯菜了  
    public void cook(IFood food);  

實現類
public class Tutu implements ITutu {  
   
    @Override 
    public void cook(IFood food) {  
        food.eat();  
    }  
   

食物介面
public interface IFood {  
    public void eat();  

這樣就為擴充套件留出了很大的空間,方面擴充套件其他的類。也不會對細節有變動。以後塗塗想吃什麼學一下就可以自己做了
實現麵條
public class Noodles implements IFood {  
   
    @Override 
    public void eat() {  
        System.out.println("塗塗吃麵條...");  
    }  
   

實現米飯
public class Rice implements IFood {  
   
    @Override 
    public void eat() {  
        System.out.println("塗塗吃米飯(終於吃上米飯了)...");  
    }  

場景類:塗塗在家裡開吃了,想吃什麼直接做就是了
public class Home {  
    public static void main(String args[])  
    {  
        //介面使不能例項化滴  
        ITutu tutu = new Tutu();  
        //例項化米飯,塗塗可以吃米飯了  
        IFood rice = new Rice();  
        //吃麵條  
        //IFood noodles = new Noodles();  
        tutu.cook(rice);  
    }  
}   
這樣各個類或模組的實現彼此獨立,不互相影響,實現了。

原文連結:http://www.cnblogs.com/loulijun/archive/2012/03/05/2380524.html

設計模式六大原則3:介面隔離原則

介面隔離原則要求的是在一個模組應該只依賴它需要的介面,以保證介面的小純潔。而且需要保證介面應該儘量小,即設計介面的時候應該讓介面儘量細化,不要定義太臃腫的介面(比如介面中有很多不相干的邏輯的方法宣告)。

首先看看介面隔離原則的定義,有兩種定義
第一種:Clients should not be forced to depend upon interfaces that they don't use.(客戶端不應該強行以來它不需要的介面)
第二種:The dependency of one class to another one should depend on the smallest possible interface.(類間的依賴關係應該建立在最小的介面上)
而這裡的介面,卻不僅僅指的是通過interface關鍵字定義的介面,介面分為2種:
1、物件介面(Object Interface)
JAVA中宣告的一個類,通過new關鍵字產生的一個例項,它是對一個型別的事物的描述,這也是一種介面。例如:
Phone phone = new Phone();這裡的類Person就是例項phone的一個介面
2、類介面(Class Interface)
這種介面就是通過interface關鍵字定義的介面了
也就是說,介面隔離原則要求的是在一個模組應該只依賴它需要的介面,以保證介面的小純潔。而且需要保證介面應該儘量小,即設計介面的時候應該讓介面儘量細化,不要定義太臃腫的介面(比如介面中有很多不相干的邏輯的方法宣告)。
介面隔離原則與單一職責原則有些相似,不過不同在於:單一職責原則要求的是類和介面職責單一,注重的是職責,是業務邏輯上的劃分。而介面隔離原則要求的是介面的方法儘量少,儘量有用(針對一個模組)
在使用介面隔離原則的時候需要有一些規範:
1.介面儘量小
介面儘量小主要是為了保證一個介面只服務一個子模組或者業務邏輯
2.介面高內聚
介面高內聚是對內高度依賴,對外儘可能隔離。即一個介面內部的宣告的方法相互之間都與某一個子模組相關,且是這個子模組必須的。
3.介面設計是有限度的
但是如果完全遵循介面隔離原則的話,會出現一個問題。即介面的設計力度會越來越小,這樣就造成了介面數量劇增,系統複雜度一下子增加了,而這不是真實專案所需要的,所以在使用這個原則的時候還要在特定的專案,根據經驗或者嘗試判斷,不過沒有一個固定的標準。
舉個例子
在春熙路上逛街,到處都是女的,有穿著絲襪的大媽(噁心一下),有文靜的女生,有性感的辣妹,總之很多女的。然而當你對前面喊一聲“美女,錢掉了”,估計前面連同大媽一起回頭看看,以為在叫自己。如今美女這個詞已經變得大眾化了,反正跟女的打招呼就說美女。但是真正的美女是這樣嗎,男淫們心中的美女應該是這樣的:身材好、長相好、氣質佳。
IPrettyGirl.java:定義美女標準
//定義美女介面  
public interface IPrettyGirl {  
    //長相好  
    public void greatLooks();  
    //好身材  
    public void greatFigure();  
    //氣質佳  
    public void greatTemperament();  

PrettyGril.java:實現美女類
public class PrettyGirl implements IPrettyGirl {  
    private String name;  
    //建構函式,美女名字  
    public PrettyGirl(String name)  
    {  
        this.name = name;  
    }  
    //好身材  
    @Override 
    public void greatFigure() {  
        System.out.println(name+":身材非常好");  
    }  
    //好長相  
    @Override 
    public void greatLooks() {  
        System.out.println(name+":長相非常好");  
    }  
    //好氣質  
    @Override 
    public void greatTemperament() {  
        System.out.println(name+":氣質非常好");  
    }  
   

AMan:是個抽象類,抽象出一個男人來
public abstract class AMan {  
    protected IPrettyGirl prettyGirl;  
    public AMan(IPrettyGirl prettyGirl)  
    {  
        this.prettyGirl = prettyGirl;  
    }  
       
    //帥哥開始找美女啦  
    public abstract void findGirl();  

Man:
public class Man extends AMan {  
   
    public Man(IPrettyGirl prettyGirl) {  
        super(prettyGirl);  
    }  
   
    @Override 
    public void findGirl() {  
        System.out.println("美女在這裡:----------------------");  
        super.prettyGirl.greatLooks();  
        super.prettyGirl.greatFigure();  
        super.prettyGirl.greatTemperament();  
           
    }  
   

場景類,春熙路,帥哥開始尋找美女了
public class ChunxiRoad {  
    public static void main(String args[])  
    {  
        IPrettyGirl jiajia = new PrettyGirl("佳佳");  
        AMan man = new Man(jiajia);  
        man.findGirl();  
    }  

執行結果:
美女在這裡:---------------------- 
佳佳:長相非常好
佳佳:身材非常好
佳佳:氣質非常好
但是這裡有個問題,介面劃分的不是很清晰,比如有些男人認為某些女生長相好,身材好就是美女(而不管這個女的素質啥樣,比如那些“壓脈帶”)。而某些女生雖然長相一般,身材也一般,但是氣質很好,這就是某些宅男心目中的氣質型美女,或者三者具備。所以需要把介面劃分的再細一點以滿足不同男人的審美觀。
我們把介面分為兩種:
好身材
public interface IGreatBody {  
    //好長相  
    public void greatLooks();  
    //身材  
    public void greatFigure();  

好氣質
public interface IGreatTemperament {  
    //氣質好  
    public void greatTemperament();  

然後我們就可以根據自己的需求來尋找自己心目中認為的美女啦,舉個例子
上面的AMan和Man傳遞的介面變為IGreatBody
接下來,我們來到了--東京。看到了cang老師
public class Tokyo {  
    public static void main(String args[])  
    {  
        IGreatBody canglaoshi = new PrettyGirl("cang老師");  
        AMan man = new Man(canglaoshi);  
        man.findGirl();  
    }  

執行結果:
美女在這裡:---------------------- 
cang老師:長相非常好 
cang老師:身材非常好 

原文連結:http://www.cnblogs.com/loulijun/archive/2012/03/07/2382247.html

設計模式六大原則4:單一職責原則

有時候,開發人員設計介面的時候會有些問題,比如使用者的屬性和使用者的行為被放在一個介面中宣告。這就造成了業務物件和業務邏輯被放在了一起,這樣就造成了這個介面有兩種職責,介面職責不明確,按照SRP的定義就違背了介面的單一職責原則了。

單一職責原則(Single Responsibility Principle),簡稱SRP。
定義:
There should never be more than one reason for a class to change.
應該有且僅有一個原因引起類的變更。
有時候,開發人員設計介面的時候會有些問題,比如使用者的屬性和使用者的行為被放在一個介面中宣告。這就造成了業務物件和業務邏輯被放在了一起,這樣就造成了這個介面有兩種職責,介面職責不明確,按照SRP的定義就違背了介面的單一職責原則了。
下面是個例子:
package com.loulijun.chapter1;  
   
public interface Itutu {  
    //身高  
    void setShengao(double height);  
    double getShengao();  
    //體重  
    void setTizhong(double weight);  
    double getTizhong();  
    //吃飯  
    boolean chiFan(boolean hungry);  
    //上網  
    boolean shangWang(boolean silly);  

上面的例子就存在這個問題,身高、體重屬於業務物件,與之相應的方法主要負責使用者的屬性。而吃飯、上網是相應的業務邏輯,主要負責使用者的行為。但是這就會給人一種不知道這個介面到底是做什麼的感覺,職責不清晰,後期維護的時候也會造成各種各樣的問題。
解決辦法:單一職責原則,將這個介面分解成兩個職責不同的介面即可
ItutuBO.java:負責tutu(塗塗,假如是個人名)的屬性
package com.loulijun.chapter1;  
   
/**  
 * BO:Bussiness Object,業務物件  
 * 負責使用者的屬性  
 * @author Administrator  
 *  
 */ 
public interface ItutuBO {  
    //身高  
    void setShengao(double height);  
    double getShengao();  
    //體重  
    void setTizhong(double weight);  
    double getTizhong();  

ItutuBL.java:負責塗塗的行為
package com.loulijun.chapter1;  
/**  
 * BL:Business Logic,業務邏輯  
 * 負責使用者的行為  
 * @author Administrator  
 *  
 */ 
public interface ItutuBL {  
    //吃飯  
    boolean chiFan(boolean hungry);  
    //上網  
    boolean shangWang(boolean silly);  

這樣就實現了介面的單一職責。那麼實現介面的時候,就需要有兩個不同的類
TutuBO.java
package com.loulijun.chapter1;  
   
public class TutuBO implements ItutuBO {  
    private double height;  
    private double weight;  
    @Override 
    public double getShengao() {         
        return height;  
    }  
   
    @Override 
    public double getTizhong() {  
        return weight;  
    }  
   
    @Override 
    public void setShengao(double height) {  
        this.height = height;  
    }  
   
    @Override 
    public void setTizhong(double weight) {  
        this.weight = weight;  
    }  
   

TutuBL.java
package com.loulijun.chapter1;  
   
public class TutuBL implements ItutuBL {  
   
    @Override 
    public boolean chiFan(boolean hungry) {  
        if(hungry)  
        {  
            System.out.println("去吃火鍋...");  
            return true;  
        }  
        return false;  
    }  
   
    @Override 
    public boolean shangWang(boolean silly) {  
        if(silly)  
        {  
            System.out.println("好無聊啊,上會網...");  
            return true;  
        }  
        return false;  
    }  
   

這樣就清晰了,當需要修改使用者屬性的時候只需要對ItutuBO這個介面來修改,只會影響到TutuBO這個類,不會影響其他類。
那麼單一職責原則的意義何在呢?
降低類的複雜性,實現什麼樣的職責都有清晰的定義
提高可讀性
提高可維護性
降低變更引起的風險,對系統擴充套件性和維護性很有幫助
但是、使用單一職責原則有一個問題,“職責”沒有一個明確的劃分標準,如果把職責劃分的太細的話會導致介面和實現類的數量劇增,反而提高了複雜度,降低了程式碼的可維護性。所以使用這個職責的時候還要具體情況具體分析。建議就是介面一定要採用單一職責原則,實現類的設計上儘可能做到單一職責原則,最好是一個原因引起一個類的變化。
原文連結:http://www.cnblogs.com/loulijun/archive/2012/03/03/2378642.html
 

設計模式六大原則5:迪米特法則

迪米特法則的核心觀念就是類間解耦,弱耦合,只有弱耦合了以後,類的複用性才可以提高。形象一點的比喻類似於:監獄內的犯人是不應該跟外面的人接觸的,當然或許會有探親的。這裡的監獄就是類,裡面的犯人就是類內部的資訊,而監獄裡的獄警就相當於迪米特法則的執行者。

迪米特法則(Law of emeter)
定義:一個物件應該對其他物件瞭解最少
迪米特法則的核心觀念就是類間解耦,弱耦合,只有弱耦合了以後,類的複用性才可以提高。
形象一點的比喻類似於:監獄內的犯人是不應該跟外面的人接觸的,當然或許會有探親的。這裡的監獄就是類,裡面的犯人就是類內部的資訊,而監獄裡的獄警就相當於迪米特法則的執行者
舉個例子
家人探望犯人
家人:家人只與犯人是親人,但是不認識他的獄友
package com.loulijun.chapter5;  
   
public class Family {  
    //家人探望犯人  
    public void visitPrisoner(Prisoners prisoners)  
    {  
        //家人希望犯人與獄友互幫互助  
        Inmates inmates = prisoners.helpEachOther();  
        //獄友說,我們是盟友  
        inmates.weAreFriend();  
    }  

犯人:犯人與家人是親人,犯人與獄友是朋友
package com.loulijun.chapter5;  
   
public class Prisoners {  
    private Inmates inmates = new Inmates();  
    public Inmates helpEachOther()  
    {  
        System.out.println("家人說:你和獄友之間應該互相幫助...");  
        return inmates;  
    }  

獄友:犯人與獄友是朋友,但是不認識他的家人
package com.loulijun.chapter5;  
//Inmates是獄友的意思  
public class Inmates {  
    public void weAreFriend()  
    {  
        System.out.println("獄友說:我們是獄友...");  
    }  

場景類:發生在監獄裡
package com.loulijun.chapter5;  
   
public class Prison {  
    public static void main(String args[])  
    {  
        Family family = new Family();  
        family.visitPrisoner(new Prisoners());  
    }  

執行結果:
家人說:你和獄友之間應該互相幫助... 
獄友說:我們是獄友...
看到這樣的結果,是不是有些彆扭,家人告訴犯人要與獄友好好相處,而獄友確冒出來說話。這顯然越界了,因為監獄只允許家人探望犯人,而不是隨便誰都可以見的
這裡的家人和獄友有了溝通是違背迪米特法則的,所以我們需要將家人和獄友隔離開,對其進行重構
家人
package com.loulijun.chapter5;  
   
public class Family {  
    //家人探望犯人  
    public void visitPrisoner(Prisoners prisoners)  
    {  
        System.out.print("家人說:");  
        prisoners.helpEachOther();  
    }  

犯人
package com.loulijun.chapter5;  
   
public class Prisoners {  
    private Inmates inmates = new Inmates();  
    public Inmates helpEachOther()  
    {  
        System.out.println("犯人和獄友之間應該互相幫助...");  
        System.out.print("犯人說:");  
        inmates.weAreFriend();  
        return inmates;  
    }  
       

獄友
package com.loulijun.chapter5;  
//Inmates是獄友的意思  
public class Inmates {  
    public void weAreFriend()  
    {  
        System.out.println("我們是獄友...");  
    }  

監獄
package com.loulijun.chapter5;  
   
public class Prison {  
    public static void main(String args[])  
    {  
        Family family = new Family();  
        family.visitPrisoner(new Prisoners());  
    }  

執行結果
家人說:犯人和獄友之間應該互相幫助... 
犯人說:我們是獄友...
這樣家人和獄友就分開了,但是也表達了家人希望獄友能跟犯人互相幫助的意願。也就是兩個類通過第三個類實現資訊傳遞
網上還有如下一些關於應用迪米特法則的注意事項:
① 在類的劃分上,應該建立有弱耦合的類;
② 在類的結構設計上,每一個類都應當儘量降低成員的訪問許可權;
③ 在類的設計上,只要有可能,一個類應當設計成不變類;
④ 在對其他類的引用上,一個物件對其它物件的引用應當降到最低;
⑤ 儘量降低類的訪問許可權;
⑥ 謹慎使用序列化功能;
⑦ 不要暴露類成員,而應該提供相應的訪問器(屬性)。
原文連結:http://www.cnblogs.com/loulijun/archive/2012/03/10/2389573.html
 

設計模式六大原則6:開閉原則

開閉原則算是前5中原則的一個抽象總結,前五種是開閉原則的一些具體實現,所以如果使用開閉原則,其實有點虛,因為它沒有一個固定的模式,但是最終保證的是提高程式的複用性、可維護性等要求。

AD:


開閉原則(Open Closed Principle)
開閉原則的核心是:對擴充套件開放,對修改關閉。
白話意思就是我們改變一個軟體時(比如擴充套件其他功能),應該通過擴充套件的方式來達到軟體的改變,而不應愛修改原有程式碼來實現變化。
開閉原則算是前5中原則的一個抽象總結,前五種是開閉原則的一些具體實現,所以如果使用開閉原則,其實有點虛,因為它沒有一個固定的模式,但是最終保證的是提高程式的複用性、可維護性等要求。
要使用這一原則還需要結合著它的思想“對擴充套件開放,對修改關閉”與其他的五大設計原則根據經驗來開發專案。
大體是這個意思,如果想深究,還需要看看其他的書籍。
下面是使用開閉原則的一個簡單示例,雖有些不準確,但是是這個意思(領會精神)。
定義一個介面,尋找美女
package com.loulijun.chapter6;  
   
public interface IFindGirl {  
    //年齡  
    public int getAge();  
    //姓名  
    public String getName();  
    //長相  
    public String getFace();  
    //身材  
    public String getFigure();  

實現這個介面
package com.loulijun.chapter6;  
   
public class FindGirl implements IFindGirl {  
    private String name;  
    private int age;  
    private String face;  
    private String figure;  
       
    public FindGirl(String name, int age, String face, String figure)  
    {  
        this.name = name;  
        this.age = age;  
        this.face = face;  
        this.figure = figure;  
    }  
   
    @Override 
    public int getAge() {  
        return age;  
    }  
   
    @Override 
    public String getFace() {  
        return face;  
    }  
   
    @Override 
    public String getFigure() {  
        return figure;  
    }  
   
    @Override 
    public String getName() {  
        return name;  
    }  
       
   

場景:大街上
package com.loulijun.chapter6;  
   
import java.text.NumberFormat;  
import java.util.ArrayList;  
   
public class Street {  
    private final static ArrayList<IFindGirl> girls = new ArrayList<IFindGirl>();  
    //靜態初始化塊  
    static 
    {  
        girls.add(new FindGirl("張含韻",23,"可愛型","165cm/47kg"));  
        girls.add(new FindGirl("高圓圓",33,"時尚型","165cm/48kg"));  
        girls.add(new FindGirl("章澤天",19,"清純型","168cm/47kg"));  
    }  
    public static void main(String args[])  
    {  
        System.out.println("----------美女在這裡----------");  
        for(IFindGirl girl:girls)  
        {  
            System.out.println("姓名:"+girl.getName()+" 年齡:"+girl.getAge()+  
                    "  長相:"+girl.getFace()+"  身材:"+girl.getFigure());  
        }  
    }  

執行結果:
----------美女在這裡----------
姓名:張含韻 年齡:23 長相:可愛型 身材:165cm/47kg
姓名:高圓圓 年齡:33 長相:時尚型 身材:165cm/48kg
姓名:章澤天 年齡:19 長相:清純型 身材:168cm/47kg
但是如果想獨立分出一個外國美女的類別的話(比如增加一個國籍),可以通過修改介面、修改實現類、通過擴充套件來實現。
如果修改介面,也就意味著修改實現類,這樣對專案的變動太大了,所以不推薦
如果修改實現類,這樣雖能解決問題,但是明顯有些牽強,如果需要其他變動的時候會顯得邏輯混亂
所以,通過擴充套件來實現是最簡單的方式
如何擴充套件:
可以定義一個IForeigner介面繼承自IFindGirl,在IForeigner介面中新增國籍屬性getCountry(),然後實現這個介面即可,然後就只需要在場景類中做稍微修改就可以了
package com.loulijun.chapter6;  
   
public interface IForeigner extends IFindGirl {  
    //國籍  
    public String getCountry();  

實現介面
package com.loulijun.chapter6;  
   
public class ForeignerGirl implements IForeigner {  
    private String name;  
    private int age;  
    private String country;  
    private String face;  
    private String figure;  
       
    public ForeignerGirl(String name, int age, String country, String face, String figure)  
    {  
        this.name = name;  
        this.age = age;  
        this.country = country;  
        this.face =face;  
        this.figure = figure;  
    }  
    @Override 
    public String getCountry() {  
        // TODO Auto-generated method stub  
        return country;  
    }  
   
    @Override 
    public int getAge() {  
        // TODO Auto-generated method stub  
        return age;  
    }  
   
    @Override 
    public String getFace() {  
        // TODO Auto-generated method stub  
        return face;  
    }  
   
    @Override 
    public String getFigure() {  
        // TODO Auto-generated method stub  
        return figure;  
    }  
   
    @Override 
    public String getName() {  
        // TODO Auto-generated method stub  
        return name;  
    }  
   

然後在場景類中只需要修改如下程式碼即可,其他不變
girls.add(new ForeignerGirl("Avirl",28,"美國","性感型","160cm/45kg")); 
不過這些設計原則到不是絕對的,而是根據專案需求,實際需求來定奪使用。

原文連結:http://www.cnblogs.com/loulijun/archive/2012/03/14/2394055.html