qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問 http://qaseven.github.io/

          java 常用設(shè)計(jì)模式(1)

          設(shè)計(jì)模式;

            一個(gè)程序員對(duì)設(shè)計(jì)模式的理解:

            “不懂”為什么要把很簡單的東西搞得那么復(fù)雜。后來隨著軟件開發(fā)經(jīng)驗(yàn)的增加才開始明白我所看到的“復(fù)雜”恰恰就是設(shè)計(jì)模式的精髓所在,我所理解的“簡單”就是一把鑰匙開一把鎖的模式,目的僅僅是著眼于解決現(xiàn)在的問題,而設(shè)計(jì)模式的“復(fù)雜”就在于它是要構(gòu)造一個(gè)“萬能鑰匙”,目的是提出一種對(duì)所有鎖的開鎖方案。在真正理解設(shè)計(jì)模式之前我一直在編寫“簡單”的代碼.

            這個(gè)“簡單”不是功能的簡單,而是設(shè)計(jì)的簡單。簡單的設(shè)計(jì)意味著缺少靈活性,代碼很鋼硬,只在這個(gè)項(xiàng)目里有用,拿到其它的項(xiàng)目中就是垃圾,我將其稱之為“一次性代碼”。

            -->要使代碼可被反復(fù)使用,請(qǐng)用'設(shè)計(jì)模式'對(duì)你的代碼進(jìn)行設(shè)計(jì).

            很多我所認(rèn)識(shí)的程序員在接觸到設(shè)計(jì)模式之后,都有一種相見恨晚的感覺,有人形容學(xué)習(xí)了設(shè)計(jì)模式之后感覺自己好像已經(jīng)脫胎換骨,達(dá)到了新的境界,還有人甚至把是否了解設(shè)計(jì)模式作為程序員劃分水平的標(biāo)準(zhǔn)。

            我們也不能陷入模式的陷阱,為了使用模式而去套模式,那樣會(huì)陷入形式主義。我們?cè)谑褂媚J降臅r(shí)候,一定要注意模式的意圖(intent),而不 要過多的去關(guān)注模式的實(shí)現(xiàn)細(xì)節(jié),因?yàn)檫@些實(shí)現(xiàn)細(xì)節(jié)在特定情況下,可能會(huì)發(fā)生一些改變。不要頑固地認(rèn)為設(shè)計(jì)模式一書中的類圖或?qū)崿F(xiàn)代碼就代表了模式本身。

            設(shè)計(jì)原則:(重要)

            1.邏輯代碼獨(dú)立到單獨(dú)的方法中,注重封裝性--易讀,易復(fù)用。

            不要在一個(gè)方法中,寫下上百行的邏輯代碼。把各小邏輯代碼獨(dú)立出來,寫于其它方法中,易讀其可重復(fù)調(diào)用。

            2.寫類,寫方法,寫功能時(shí),應(yīng)考慮其移植性,復(fù)用性:防止一次性代碼!

            是否可以拿到其它同類事物中應(yīng)該?是否可以拿到其它系統(tǒng)中應(yīng)該?

            3.熟練運(yùn)用繼承的思想:

            找出應(yīng)用中相同之處,且不容易發(fā)生變化的東西,把它們抽取到抽象類中,讓子類去繼承它們;

            繼承的思想,也方便將自己的邏輯建立于別人的成果之上。如ImageField extends JTextField;

            熟練運(yùn)用接口的思想:

            找出應(yīng)用中可能需要變化之處,把它們獨(dú)立出來,不要和那些不需要變化的代碼混在一起。

            把很簡單的東西搞得那么復(fù)雜,一次性代碼,設(shè)計(jì)模式優(yōu)勢(shì)的實(shí)例說明:(策略模式)

            說明:

            模擬鴨子游戲的應(yīng)用程序,要求:游戲中會(huì)出現(xiàn)各種顏色外形的鴨子,一邊游泳戲水,一邊呱呱叫。

            第一種方法:(一次性代碼)

            直接編寫出各種鴨子的類:MallardDuck//野鴨,RedheadDuck//紅頭鴨,各類有三個(gè)方法:

            quack():叫的方法

            swim():游水的方法

            display():外形的方法

            第二種方法:運(yùn)用繼承的特性,將其中共同的部分提升出來,避免重復(fù)編程。

            即:設(shè)計(jì)一個(gè)鴨子的超類(Superclass),并讓各種鴨子繼承這個(gè)超類。

          public class Duck{
          public void quack(){  //呱呱叫
          System.out.println("呱呱叫");
          }
          public void swim(){   //游泳
          System.out.println(" 游泳");
          }
          public  abstratact void display(); /*因?yàn)橥庥^不一樣,讓子類自己去決定了。*/
          }

            對(duì)于它的子類只需簡單的繼承就可以了,并實(shí)現(xiàn)自己的display()方法。

          //野鴨
          public class MallardDuck extends Duck{
          public void display(){
          System.out.println("野鴨的顏色...");
          }
          }
          //紅頭鴨
          public class RedheadDuck extends Duck{
          public void display(){
          System.out.println("紅頭鴨的顏色...");
          }
          }

            不幸的是,現(xiàn)在客戶又提出了新的需求,想讓鴨子飛起來。這個(gè)對(duì)于我們OO程序員,在簡單不過了,在超類中在加一個(gè)方法就可以了。

          public class Duck{
          public void quack(){  //呱呱叫
          System.out.println("呱呱叫");
          }
          public void swim(){   //游泳
          System.out.println(" 游泳");
          }
          public  abstract void display(); /*因?yàn)橥庥^不一樣,讓子類自己去決定了。*/
          public void fly(){
          System.out.println("飛吧!鴨子");
          }
          }

            對(duì)于不能飛的鴨子,在子類中只需簡單的覆蓋。

          //殘廢鴨
          public class DisabledDuck extends Duck{
          public void display(){
          System.out.println("殘廢鴨的顏色...");
          }
          public void fly(){
          //覆蓋,變成什么事都不做。
          }
          }

            其它會(huì)飛的鴨子不用覆蓋。

            這樣所有的繼承這個(gè)超類的鴨子都會(huì)fly了。但是問題又出來了,客戶又提出有的鴨子會(huì)飛,有的不能飛。

            >>>>>>點(diǎn)評(píng):

            對(duì)于上面的設(shè)計(jì),你可能發(fā)現(xiàn)一些弊端,如果超類有新的特性,子類都必須變動(dòng),這是我們開發(fā)最不喜歡看到的,一個(gè)類變讓另一個(gè)類也跟著變,這有點(diǎn)不符合OO設(shè)計(jì)了。這樣很顯然的耦合了一起。利用繼承-->耦合度太高了.

            第三種方法:用接口改進(jìn).

            我們把容易引起變化的部分提取出來并封裝之,來應(yīng)付以后的變法。雖然代碼量加大了,但可用性提高了,耦合度也降低了。

            我們把Duck中的fly方法和quack提取出來。

          public interface Flyable{
          public void fly();
          }
          public interface Quackable{
          public void quack();
          }
          最后Duck的設(shè)計(jì)成為:
          public class Duck{
          public void swim(){   //游泳
          System.out.println(" 游泳");
          }
          public  abstract void display(); /*因?yàn)橥庥^不一樣,讓子類自 己去決定了。*/
          }
          而MallardDuck,RedheadDuck,DisabledDuck 就可以寫成為:
          //野鴨
          public class MallardDuck extends Duck  implements Flyable,Quackable{
          public void display(){
          System.out.println("野鴨的顏色...");
          }
          public void fly(){
          //實(shí)現(xiàn)該方法
          }
          public void quack(){
          //實(shí)現(xiàn)該方法
          }
          }
          //紅頭鴨
          public class RedheadDuck extends Duck implements Flyable,Quackable{
          public void display(){
          System.out.println("紅頭鴨的顏色...");
          }
          public void fly(){
          //實(shí)現(xiàn)該方法
          }
          public void quack(){
          //實(shí)現(xiàn)該方法
          }
          }
          //殘廢鴨 只實(shí)現(xiàn)Quackable(能叫不能飛)
          public class DisabledDuck extends Duck implements Quackable{
          public void display(){
          System.out.println("殘廢鴨的顏色...");
          }
          public void quack(){
          //實(shí)現(xiàn)該方法
          }
          }

            >>>>>>點(diǎn)評(píng):

            好處:

            這樣已設(shè)計(jì),我們的程序就降低了它們之間的耦合。

            不足:

            Flyable和 Quackable接口一開始似乎還挺不錯(cuò)的,解決了問題(只有會(huì)飛到鴨子才實(shí)現(xiàn) Flyable),但是Java接口不具有實(shí)現(xiàn)代碼,所以實(shí)現(xiàn)接口無法達(dá)到代碼的復(fù)用。

            第四種方法:對(duì)上面各方式的總結(jié):

            繼承的好處:讓共同部分,可以復(fù)用.避免重復(fù)編程.

            繼承的不好:耦合性高.一旦超類添加一個(gè)新方法,子類都繼承,擁有此方法,

            若子類相當(dāng)部分不實(shí)現(xiàn)此方法,則要進(jìn)行大批量修改.

            繼承時(shí),子類就不可繼承其它類了.

            接口的好處:解決了繼承耦合性高的問題.

            且可讓實(shí)現(xiàn)類,繼承或?qū)崿F(xiàn)其它類或接口.

            接口的不好:不能真正實(shí)現(xiàn)代碼的復(fù)用.可用以下的策略模式來解決.

            ------------------------- strategy(策略模式) -------------------------

            我們有一個(gè)設(shè)計(jì)原則:

            找出應(yīng)用中相同之處,且不容易發(fā)生變化的東西,把它們抽取到抽象類中,讓子類去繼承它們;

            找出應(yīng)用中可能需要變化之處,把它們獨(dú)立出來,不要和那些不需要變化的代碼混在一起。 -->important.

            現(xiàn)在,為了要分開“變化和不變化的部分”,我們準(zhǔn)備建立兩組類(完全遠(yuǎn)離Duck類),一個(gè)是"fly"相關(guān)的,另一個(gè)

            是“quack”相關(guān)的,每一組類將實(shí)現(xiàn)各自的動(dòng)作。比方說,我們可能有一個(gè)類實(shí)現(xiàn)“呱呱叫”,另一個(gè)類實(shí)現(xiàn)“吱吱

            叫”,還有一個(gè)類實(shí)現(xiàn)“安靜”。

            首先寫兩個(gè)接口。FlyBehavior(飛行行為)和QuackBehavior(叫的行為).

          public interface FlyBehavior{
          public void fly();
          }
          public interface QuackBehavior{
          public void quack();
          }
          我們?cè)诙x一些針對(duì)FlyBehavior的具體實(shí)現(xiàn)。
          public class FlyWithWings implements FlyBehavior{
          public void  fly(){
          //實(shí)現(xiàn)了所有有翅膀的鴨子飛行行為。
          }
          }
          public class FlyNoWay implements FlyBehavior{
          public void  fly(){
          //什么都不做,不會(huì)飛
          }
          }
          針對(duì)QuackBehavior的幾種具體實(shí)現(xiàn)。
          public class Quack implements QuackBehavior{
          public void quack(){
          //實(shí)現(xiàn)呱呱叫的鴨子
          }
          }
          public class Squeak implements QuackBehavior{
          public void quack(){
          //實(shí)現(xiàn)吱吱叫的鴨子
          }
          }
          public class MuteQuack implements QuackBehavior{
          public void quack(){
          //什么都不做,不會(huì)叫
          }
          }

            點(diǎn)評(píng)一:

            這樣的設(shè)計(jì),可以讓飛行和呱呱叫的動(dòng)作被其他的對(duì)象復(fù)用,因?yàn)檫@些行為已經(jīng)與鴨子類無關(guān)了。而我們?cè)黾右恍┬碌男袨椋粫?huì)影響到既有的行為類,也不會(huì)影響“使用”到飛行行為的鴨子類。

            最后我們看看Duck 如何設(shè)計(jì)。

          public class Duck{        --------->在抽象類中,聲明各接口,定義各接口對(duì)應(yīng)的方法.
          FlyBehavior flyBehavior;//接口
          QuackBehavior quackBehavior;//接口
          public Duck(){}
          public abstract void display();
          public void swim(){
          //實(shí)現(xiàn)游泳的行為
          }
          public void performFly(){
          flyBehavior.fly();  -->由于是接口,會(huì)根據(jù)繼承類實(shí)現(xiàn)的方式,而調(diào)用相應(yīng)的方法.
          }
          public void performQuack(){
          quackBehavior.quack();();
          }
          }

            看看MallardDuck如何實(shí)現(xiàn)。

            ----->通過構(gòu)造方法,生成'飛','叫'具體實(shí)現(xiàn)類的實(shí)例,從而指定'飛','叫'的具體屬性

          public class MallardDuck extends Duck{
          public MallardDuck {
          flyBehavior = new FlyWithWings ();
          quackBehavior = new Quack();
          //因?yàn)镸allardDuck 繼承了Duck,所有具有flyBehavior 與quackBehavior 實(shí)例變量}
          public void display(){
          //實(shí)現(xiàn)
          }
          }

            這樣就滿足了即可以飛,又可以叫,同時(shí)展現(xiàn)自己的顏色了。

            這樣的設(shè)計(jì)我們可以看到是把flyBehavior ,quackBehavior 的實(shí)例化寫在子類了。我們還可以動(dòng)態(tài)的來決定。

            我們只需在Duck中加上兩個(gè)方法。

           在構(gòu)造方法中對(duì)屬性進(jìn)行賦值與用屬性的setter的區(qū)別:

            構(gòu)造方法中對(duì)屬性進(jìn)行賦值:固定,不可變;

            用屬性的setter,可以在實(shí)例化對(duì)象后,動(dòng)態(tài)的變化,比較靈活。

          public class Duck{
          FlyBehavior flyBehavior;//接口
          QuackBehavior quackBehavior;//接口
          public void setFlyBehavior(FlyBehavior flyBehavior){
          this.flyBehavior = flyBehavior;
          }
          public void setQuackBehavior(QuackBehavior quackBehavior  {
          this.quackBehavior= quackBehavior;
          }
          }

            ------------------------- static Factory Method(靜態(tài)工廠) -------------------------

            (1)在設(shè)計(jì)模式中,Factory Method也是比較簡單的一個(gè),但應(yīng)用非常廣泛,EJB,RMI,COM,CORBA,Swing中都可以看到此模式的影子,它是最重要的模式之一.在很多地方我們都會(huì)看到xxxFactory這樣命名的類.

            (2)基本概念:

            FactoryMethod是一種創(chuàng)建性模式,它定義了一個(gè)創(chuàng)建對(duì)象的接口,但是卻讓子類來決定具體實(shí)例化哪一個(gè)類.

            通常我們將Factory Method作為一種標(biāo)準(zhǔn)的創(chuàng)建對(duì)象的方法。

            應(yīng)用方面:

            當(dāng)一個(gè)類無法預(yù)料要?jiǎng)?chuàng)建哪種類的對(duì)象或是一個(gè)類需要由子類來指定創(chuàng)建的對(duì)象時(shí)我們就需要用到Factory Method 模式了.

            -------------------------------- singelton(單例模式) --------------------------------

            基本概念:

            Singleton 是一種創(chuàng)建性模型,它用來確保只產(chǎn)生一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn).對(duì)一些類來說,保證只有一個(gè)實(shí)例是很重要的,比如有的時(shí)候,數(shù)據(jù)庫連接或 Socket 連接要受到一定的限制,必須保持同一時(shí)間只能有一個(gè)連接的存在.

            運(yùn)用:

            在于使用static變量;

            創(chuàng)建類對(duì)象,一般是在構(gòu)造方法中,或用一個(gè)方法來創(chuàng)建類對(duì)象。在這里方法中,加對(duì)相應(yīng)的判斷即可。

            單態(tài)模式與共享模式的區(qū)別:

            單態(tài)模式與共享模式都是讓類的實(shí)例是唯一的。

            但單態(tài)模式的實(shí)現(xiàn)方式是:

            在類的內(nèi)部.即在構(gòu)造方法中,或靜態(tài)的getInstace方法中,進(jìn)行判斷,若實(shí)例存在,則直接返回,不進(jìn)行創(chuàng)建;

            共享模式的實(shí)現(xiàn)方式是:

            每次要用到此實(shí)例時(shí),先去此hashtable中獲取,若獲取為空,則生成實(shí)例,且將類的實(shí)例放在一人hashtable中,若獲取不為空,則直接用此實(shí)例。

            (2)實(shí)例一:

          public class Singleton {
          private static Singleton s;
          public static Singleton getInstance() {
          if (s == null)
          s = new Singleton();
          return s;
          }
          }
          // 測(cè)試類
          class singletonTest {
          public static void main(String[] args) {
          Singleton s1 = Singleton.getInstance();
          Singleton s2 = Singleton.getInstance();
          if (s1==s2)
          System.out.println("s1 is the same instance with s2");
          else
          System.out.println("s1 is not the same instance with s2");
          }
          }

            singletonTest運(yùn)行結(jié)果是:

            s1 is the same instance with s2

            (3)實(shí)例二:

          class Singleton {
          static boolean instance_flag = false; // true if 1 instance
          public Singleton() {
          if (instance_flag)
          throw new SingletonException("Only one instance allowed");
          else
          instance_flag = true; // set flag for 1 instance
          }
          }

            -------------------------------- 觀察者模式(Observer) --------------------------------

            (1)基本概念:

            觀察者模式屬于行為型模式,其意圖是定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。

            這一個(gè)模式的關(guān)鍵對(duì)象是目標(biāo)(Subject)和觀察者(Observer)。一個(gè)目標(biāo)可以有任意數(shù)目的依賴它的觀察者,一旦目標(biāo)的狀態(tài)發(fā)生改變,所有的觀察者都得到通知,作為對(duì)這個(gè)通知的響應(yīng),每個(gè)觀察者都將查詢目標(biāo)以使其狀態(tài)與目標(biāo)的狀態(tài)同步。

            適用場(chǎng)景:

            觀察者模式,用于存在一對(duì)多依賴關(guān)系的對(duì)象間,當(dāng)被依賴者變化時(shí),通知依賴者全部進(jìn)行更新。因此,被依賴者,應(yīng)該有添加/刪除依賴者的方法,且可以將添加的依賴者放到一個(gè)容器中;且有一個(gè)方法去通知依賴者進(jìn)行更新。

            (2)思想:

            (一)建立目標(biāo)(subject)與觀察者(observer)接口:

            目標(biāo)(subject)接口:

            建立一個(gè)注冊(cè)觀察者對(duì)象的接口; public void attach(Observer o);

            建立一個(gè)刪除觀察者對(duì)象的接口; public void detach(Observer o);

            建立一個(gè)當(dāng)目標(biāo)狀態(tài)發(fā)生改變時(shí),發(fā)布通知給觀察者對(duì)象的接口; public void notice();

            觀察者(observer)接口:

            建立一個(gè)當(dāng)收到目標(biāo)通知后的更新接口: public void update();

            (3)實(shí)例:

            老師又電話號(hào)碼,學(xué)生需要知道老師的電話號(hào)碼以便于在合時(shí)的時(shí)候撥打,在這樣的組合中,老師就是一個(gè)被觀察者(Subject),學(xué)生就是需要知道信息的觀察者,當(dāng)老師的電話號(hào)碼發(fā)生改變時(shí),學(xué)生得到通知,并更新相應(yīng)的電話記錄。

            具體實(shí)例如下:

          Subject代碼:
          public interface Subject{
          public void attach(Observer o);
          public void detach(Observer o);
          public void notice();
          }

          Observer代碼:
          public interface Observer{
          public void update();
          }

          Teacher代碼;
          import java.util.Vector;
          public class Teacher implements Subject{
          private String phone;
          private Vector students;
          public Teacher(){
          phone = "";
          students = new Vector();
          }
          public  void attach(Observer o){
          students.add(o);
          }
          public void detach(Observer o){
          students.remove(o);
          }
          public void notice(){
          for(int i=0;i<students.size();i++)
          ((Observer)students.get(i)).update();
          }
          public void setPhone(String phone){
          this.phone = phone;
          notice();    --關(guān)鍵
          }
          public String getPhone(){
          return phone;
          }
          }

          Student代碼:
          public class Student implements Observer{
          private String name;
          private String phone;
          private Teacher teacher;
          public Student(String name,Teacher t){
          this.name = name;
          teacher = t;
          }
          public void show(){
          System.out.println("Name:"+name+"\nTeacher'sphone:"+phone);
          }
          public void update(){
          phone = teacher.getPhone();
          }
          }

          Client代碼:
          package observer;
          import java.util.Vector;
          public class Client{         -->可以只定義目標(biāo)者,觀察者,另外的vector,只為了輸入結(jié)果.
          public static void main(String[] args){
          Vector students = new Vector();
          Teacher t = new Teacher();
          for(int i= 0 ;i<10;i++){
          Student st = new Student("lili"+i,t);
          students.add(st);
          t.attach(st);
          }
          t.setPhone("88803807");
          for(int i=0;i<10;i++)
          ((Student)students.get(i)).show();
          t.setPhone("88808880");
          for(int i=0;i<10;i++)
          ((Student)students.get(i)).show();
          }
          }

            總結(jié):Observer模式的最知名的應(yīng)用是在MVC結(jié)構(gòu),Observer模式可以很好的應(yīng)用在文檔和圖表程序的制作中。


           (1)基本概念:

            迭代器模式屬于行為型模式,其意圖是提供一種方法順序訪問一個(gè)聚合對(duì)象中得各個(gè)元素,而又不需要暴露該對(duì)象的內(nèi)部表示。

            至少可以歷遍first,next,previous,last,isOver,或是歷遍選擇符合某種條件的子元素.

            (2)結(jié)構(gòu):

            由一個(gè)接口與一個(gè)實(shí)現(xiàn)類組成.

            接口: 主要是定義各歷遍的方法.

            實(shí)現(xiàn)類: 需要一個(gè)計(jì)算點(diǎn)private int current=0 ; 以及一個(gè)容器Vector,來存在原來的進(jìn)行歷遍的一團(tuán)東西;再對(duì)接口方法進(jìn)行實(shí)現(xiàn).

            (3)實(shí)例:

            Iterator接口:

            package iterator;

            public interface Iterator{

            /*

            Item:即是集合中的各對(duì)象的類型.若為String,即把所有的ITEM改為String,若為其它自定義的類,則改為各自定義的類的接口,或類. --->important.

          */
          public Item first();
          public Item next();
          public boolean isDone();
          public Item currentItem();
          }
          Controller類實(shí)現(xiàn)了Iterator接口。
          package iterator;
          import java.util.Vector;
          public class Controller implements Iterator{
          private int current =0;
          Vector channel;
          public Controller(Vector v){
          channel = v;
          }
          public Item first(){
          current = 0;
          return (Item)channel.get(current);
          }
          public Item next(){
          current ++;
          return (Item)channel.get(current);
          }
          public Item currentItem(){
          return (Item)channel.get(current);
          }
          public boolean isDone(){
          return current>= channel.size()-1;
          }
          }
          Television接口:
          package iterator;
          import java.util.Vector;
          public interface Television{
          public Iterator createIterator();
          }
          HaierTV類實(shí)現(xiàn)了Television接口。
          package iterator;
          import java.util.Vector;
          public class HaierTV implements Television{     ---對(duì)象
          private Vector channel;
          public HaierTV(){
          channel = new Vector();
          channel.addElement(new Item("channel 1")); --各元素,用VECTOR存放
          channel.addElement(new Item("channel 2"));
          channel.addElement(new Item("channel 3"));
          channel.addElement(new Item("channel 4"));
          channel.addElement(new Item("channel 5"));
          channel.addElement(new Item("channel 6"));
          channel.addElement(new Item("channel 7"));
          }
          public Iterator createIterator(){
          return new Controller(channel);          --把這個(gè)VECTOR放到迭代器中構(gòu)造方法中去
          }
          }
          Client客戶端:
          package iterator;
          public class Client{
          public static void main(String[] args){
          Television tv = new HaierTV();
          Iterator it =tv.createIterator();
          System.out.println(it.first().getName());
          while(!it.isDone()){
          System.out.println(it.next().getName());
          }
          }
          }
          Item類的接口:
          package iterator;
          public class Item{
          private String name;
          public Item(String aName){
          name = aName;
          }
          public String getName(){
          return name;
          }
          }

            ------------------------------ 外觀模式(Facade) -------------------------------

            (1)外觀模式屬于結(jié)構(gòu)型模式,F(xiàn)acade模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。外觀模式的主要用途就是為子系統(tǒng)的復(fù)雜處理過程提供方便的調(diào)用方法,使得子系統(tǒng)更加容易被使用。

            -->將復(fù)雜的過程包含在里面,提供一個(gè)簡單的應(yīng)用接口即可.

            (2)例如在一個(gè)泡茶的過程中,需要作如下的工作:燒開水,準(zhǔn)備茶葉,把茶葉放在被子里,把燒開的水放到茶杯中,只有經(jīng)過這些過程之后才能泡出好的茶葉來。這是一個(gè)常用的步驟,80%的泡茶步驟都是這個(gè)樣子的,可以把這些動(dòng)作串聯(lián)起來,形成一個(gè)整體的步驟.如下例的MakeACuppa(),使用了facade的模式,這樣在調(diào)用步方法時(shí)就比較方便。這便是外觀模式,里面的細(xì)節(jié)被屏蔽掉了。

          public class TeaCup{.....}
          public class TeaBag{.....}
          public class Water{.....}
          public class FacadeCuppaMaker{
          private boolean TeaBagIsSteeped;
          public FacadeCuppaMaker(){
          System.out.println("FacadeCuppaMaker 準(zhǔn)備好沖茶了");
          }
          public TeaCup makeACuppa(){
          TeaCup cup = new TeaCup();
          TeaBag teaBag= new TeaBag();
          Water water = new Water();
          cup.addFacadeTeaBag(teaBag);
          water.boilFacadeWater();
          cup.addFacadeWater(water);
          cup.steepTeaBag();
          return cup;
          }
          }



           ------------------------------ 適配器模式(adapter) -------------------------------

            (1)適配器模式的意圖是將一個(gè)已存在的類/接口進(jìn)行復(fù)用,將其轉(zhuǎn)換/具體化成客戶希望的另外的一個(gè)類/接口。

            (2)如何實(shí)例復(fù)用:

            將要進(jìn)行復(fù)用的類,放到目標(biāo)類的構(gòu)造方法中,進(jìn)行實(shí)例化,然后在目標(biāo)類的相應(yīng)方法中,進(jìn)行調(diào)用,修改原來方法中的參數(shù),或添加相應(yīng)的邏輯。即復(fù)用了已有類的原來方法。

            要被復(fù)用的類:

          public class Adaptee{
          public long getPower(long base,long exp){
          long result=1;
          for(int i=0;i<exp;i++)
          result*=base;
          return result;
          }
          }

            目標(biāo)類:--也可直接實(shí)現(xiàn),不用接口。

          public interface Target{
          public long get2Power(long exp);
          }
          public class Adapter implements Target{
          private Adaptee pt;
          public Adapter(){
          pt = new Adaptee();
          }
          public long get2Power(long exp){
          return pt.getPower(2,exp);   ---修改原來方法中的參數(shù),
          }
          }

            (3)又如:在SCM中添加的方法:

            已有接口:

            public boolean updateRecordStates(Double recordId,Double tableNameMapping,int state,boolean

            subRecordUpdate) throws RemoteException;

            已有實(shí)現(xiàn)類:

          public boolean updateRecordStates(Double recordId,Double tableNameMapping,int state,boolean
          subRecordUpdate) throws RemoteException
          {
          return moveTable.updateRecordStates(recordId,tableNameMapping,state,subRecordUpdate);
          }

            若采用適配器模式:

            接口:

            public boolean updateStatesAdapterForSelfPanel(Double recordId,Double tableNameMapping,int state)

            throws RemoteException;

            實(shí)現(xiàn)類:

          public boolean updateStatesAdapterForSelfPanel(Double recordId,Double tableNameMapping,int state)
          throws RemoteException
          {
          return this.updateRecordStates(recordId,tableNameMapping,state,false);
          }

          相關(guān)文章:

          java常用的設(shè)計(jì)模式(2)

          posted on 2013-08-06 10:22 順其自然EVO 閱讀(292) 評(píng)論(0)  編輯  收藏


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2013年8月>
          28293031123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 元氏县| 禄劝| 获嘉县| 武陟县| 南陵县| 吉木乃县| 新昌县| 平谷区| 牙克石市| 噶尔县| 航空| 霍州市| 当涂县| 微山县| 会昌县| 江阴市| 沭阳县| 太仆寺旗| 定南县| 淮南市| 乌拉特前旗| 津市市| 长沙县| 宜阳县| 晋中市| 治多县| 会理县| 丰镇市| 绥江县| 本溪市| 宁明县| 怀仁县| 汉川市| 张家川| 太和县| 南岸区| 犍为县| 佛坪县| 昭平县| 嘉黎县| 镇坪县|