亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Java溫故而知新(5)設計模式詳解(23種)

2019-11-14 15:31:48
字體:
來源:轉載
供稿:網友

一、設計模式的理解

剛開始“不懂”為什么要把很簡單的東西搞得那么復雜。后來隨著軟件開發經驗的增加才開始明白我所看到的“復雜”恰恰就是設計模式的精髓所在,我所理解的“簡單”就是一把鑰匙開一把鎖的模式,目的僅僅是著眼于解決現在的問題,而設計模式的“復雜”就在于它是要構造一個“萬能鑰匙”,目的是提出一種對所有鎖的開鎖方案。在真正理解設計模式之前我一直在編寫“簡單”的代碼.
這個“簡單”不是功能的簡單,而是設計的簡單。簡單的設計意味著缺少靈活性,代碼很鋼硬,只在這個項目里有用,拿到其它的項目中就是垃圾,我將其稱之為“一次性代碼”。

-->要使代碼可被反復使用,請用'設計模式'對你的代碼進行設計.
很多我所認識的程序員在接觸到設計模式之后,都有一種相見恨晚的感覺,有人形容學習了設計模式之后感覺自己好像已經脫胎換骨,達到了新的境界,還有人甚至把是否了解設計模式作為程序員劃分水平的標準。
我們也不能陷入模式的陷阱,為了使用模式而去套模式,那樣會陷入形式主義。我們在使用模式的時候,一定要注意模式的意圖(intent),而不 要過多的去關注模式的實現細節,因為這些實現細節在特定情況下,可能會發生一些改變。不要頑固地認為設計模式一書中的類圖或實現代碼就代表了模式本身。

二、設計模式的分類

總體來說設計模式分為三大類:

  1. 創建型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
  2. 結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
  3. 行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。

其實還有兩類:并發型模式和線程池模式。

三、設計模式的六大原則

1、開閉原則(Open Close PRinciple)

開閉原則就是說對擴展開放,對修改關閉。在程序需要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。所以一句話概括就是:為了使程序的擴展性好,易于維護和升級。想要達到這樣的效果,我們需要使用接口和抽象類,后面的具體設計中我們會提到這點。

2、里氏代換原則(Liskov Substitution Principle)

里氏代換原則(Liskov Substitution Principle LSP)面向對象設計的基本原則之一。 里氏代換原則中說,任何基類可以出現的地方,子類一定可以出現。 LSP是繼承復用的基石,只有當衍生類可以替換掉基類,軟件單位的功能不受到影響時,基類才能真正被復用,而衍生類也能夠在基類的基礎上增加新的行為。里氏代換原則是對“開-閉”原則的補充。實現“開-閉”原則的關鍵步驟就是抽象化。而基類與子類的繼承關系就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規范。—— From Baidu 百科

3、依賴倒轉原則(Dependence Inversion Principle)

這個是開閉原則的基礎,具體內容:真對接口編程,依賴于抽象而不依賴于具體。

4、接口隔離原則(Interface Segregation Principle)

這個原則的意思是:使用多個隔離的接口,比使用單個接口要好。還是一個降低類之間的耦合度的意思,從這兒我們看出,其實設計模式就是一個軟件的設計思想,從大型軟件架構出發,為了升級和維護方便。所以上文中多次出現:降低依賴,降低耦合。

5、迪米特法則(最少知道原則)(Demeter Principle)

為什么叫最少知道原則,就是說:一個實體應當盡量少的與其他實體之間發生相互作用,使得系統功能模塊相對獨立。

6、合成復用原則(Composite Reuse Principle)

原則是盡量使用合成/聚合的方式,而不是使用繼承。

補充:

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

不要在一個方法中,寫下上百行的邏輯代碼。把各小邏輯代碼獨立出來,寫于其它方法中,易讀其可重復調用。

2.寫類,寫方法,寫功能時,應考慮其移植性,復用性:防止一次性代碼!

是否可以拿到其它同類事物中應該?是否可以拿到其它系統中應該?

3.熟練運用繼承的思想:

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

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

熟練運用接口的思想:找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起。

四、各設計模式詳解

把很簡單的東西搞得那么復雜,一次性代碼,設計模式優勢的實例說明:(策略模式)
說明:
模擬鴨子游戲的應用程序,要求:游戲中會出現各種顏色外形的鴨子,一邊游泳戲水,一邊呱呱叫。
第一種方法:(一次性代碼)
直接編寫出各種鴨子的類:MallardDuck//野鴨,RedheadDuck//紅頭鴨,各類有三個方法:
quack():叫的方法
swim():游水的方法
display():外形的方法
第二種方法:運用繼承的特性,將其中共同的部分提升出來,避免重復編程。
即:設計一個鴨子的超類(Superclass),并讓各種鴨子繼承這個超類。
public class Duck{
     public void quack(){  //呱呱叫
              System.out.println("呱呱叫");
      }
     public void swim(){   //游泳
            System.out.println(" 游泳");
      }    
     public  abstratact void display(); /*因為外觀不一樣,讓子類自己去決定了。*/
}
對于它的子類只需簡單的繼承就可以了,并實現自己的display()方法。
//野鴨
 public class MallardDuck extends Duck{
     public void display(){
          System.out.println("野鴨的顏色...");
   }
 }
//紅頭鴨
 public class RedheadDuck extends Duck{
     public void display(){
          System.out.println("紅頭鴨的顏色...");
   }
}
不幸的是,現在客戶又提出了新的需求,想讓鴨子飛起來。這個對于我們OO程序員,在簡單不過了,在超類中在加一
個方法就可以了。
public class Duck{
     public void quack(){  //呱呱叫
              System.out.println("呱呱叫");
      }
     public void swim(){   //游泳
            System.out.println(" 游泳");
    }    
    public  abstract void display(); /*因為外觀不一樣,讓子類自己去決定了。*/
   public void fly(){
        System.out.println("飛吧!鴨子"); 
  }
}
對于不能飛的鴨子,在子類中只需簡單的覆蓋。
//殘廢鴨
 public class DisabledDuck extends Duck{
     public void display(){
          System.out.println("殘廢鴨的顏色...");
   }
   public void fly(){
    //覆蓋,變成什么事都不做。 
  }

其它會飛的鴨子不用覆蓋。
這樣所有的繼承這個超類的鴨子都會fly了。但是問題又出來了,客戶又提出有的鴨子會飛,有的不能飛。
>>>>>>點評:
對于上面的設計,你可能發現一些弊端,如果超類有新的特性,子類都必須變動,這是我們開發最不喜歡看到的,一個類變讓另一個類也跟著變,這有點不符合OO設計了。這樣很顯然的耦合了一起。利用繼承-->耦合度太高了.
第三種方法:
用接口改進.

我們把容易引起變化的部分提取出來并封裝之,來應付以后的變法。雖然代碼量加大了,但可用性提高了,耦合度也降低了。
我們把Duck中的fly方法和quack提取出來。
    public interface Flyable{
      public void fly(); 
  }
   public interface Quackable{
     public void quack();
  }
  最后Duck的設計成為:
public class Duck{
     public void swim(){   //游泳
            System.out.println(" 游泳");
    }    
    public  abstract void display(); /*因為外觀不一樣,讓子類自 己去決定了。*/
}
 而MallardDuck,RedheadDuck,DisabledDuck 就可以寫成為:
//野鴨
 public class MallardDuck extends Duck  implements Flyable,Quackable{
     public void display(){
          System.out.println("野鴨的顏色...");
   }
   public void fly(){
    //實現該方法
  }
   public void quack(){
    //實現該方法
  }
 }
//紅頭鴨
 public class RedheadDuck extends Duck implements Flyable,Quackable{
     public void display(){
          System.out.println("紅頭鴨的顏色...");
   }
   public void fly(){
    //實現該方法
  }
   public void quack(){
    //實現該方法
  }

//殘廢鴨 只實現Quackable(能叫不能飛)
 public class DisabledDuck extends Duck implements Quackable{
     public void display(){
          System.out.println("殘廢鴨的顏色...");
   }
   public void quack(){
    //實現該方法
  }
}
>>>>>>點評:
好處:
這樣已設計,我們的程序就降低了它們之間的耦合。
不足:
Flyable和 Quackable接口一開始似乎還挺不錯的,解決了問題(只有會飛到鴨子才實現 Flyable),但是java接口不具有實現代碼,所以實現接口無法達到代碼的復用。
第四種方法:
對上面各方式的總結:
繼承的好處:讓共同部分,可以復用.避免重復編程.
繼承的不好:耦合性高.一旦超類添加一個新方法,子類都繼承,擁有此方法,
                        若子類相當部分不實現此方法,則要進行大批量修改.
                         繼承時,子類就不可繼承其它類了.
接口的好處:解決了繼承耦合性高的問題.
                         且可讓實現類,繼承或實現其它類或接口.
接口的不好:不能真正實現代碼的復用.可用以下的策略模式來解決.

------------------------- strategy(策略模式) -------------------------
我們有一個設計原則:
找出應用中相同之處,且不容易發生變化的東西,把它們抽取到抽象類中,讓子類去繼承它們;
找出應用中可能需要變化之處,把它們獨立出來,不要和那些不需要變化的代碼混在一起。 -->important.

現在,為了要分開“變化和不變化的部分”,我們準備建立兩組類(完全遠離Duck類),一個是"fly"相關的,另一個
是“quack”相關的,每一組類將實現各自的動作。比方說,我們可能有一個類實現“呱呱叫”,另一個類實現“吱吱
叫”,還有一個類實現“安靜”。
首先寫兩個接口。FlyBehavior(飛行行為)和QuackBehavior(叫的行為).
  public interface FlyBehavior{
     public void fly();     
 }
 public interface QuackBehavior{
     public void quack();
 }
 我們在定義一些針對FlyBehavior的具體實現。
 public class FlyWithWings implements FlyBehavior{
    public void  fly(){
     //實現了所有有翅膀的鴨子飛行行為。
   }
 }
public class FlyNoWay implements FlyBehavior{
 
    public void  fly(){
      //什么都不做,不會飛
    }
 }   
針對QuackBehavior的幾種具體實現。
public class Quack implements QuackBehavior{
    public void quack(){
      //實現呱呱叫的鴨子
  }
}
 
public class Squeak implements QuackBehavior{
    public void quack(){
      //實現吱吱叫的鴨子 
  }
}
 
public class MuteQuack implements QuackBehavior{
    public void quack(){
      //什么都不做,不會叫
  }
}
點評一:
這樣的設計,可以讓飛行和呱呱叫的動作被其他的對象復用,因為這些行為已經與鴨子類無關了。而我們增加一些新
的行為,不會影響到既有的行為類,也不會影響“使用”到飛行行為的鴨子類。
最后我們看看Duck 如何設計。
     public class Duck{        --------->在抽象類中,聲明各接口,定義各接口對應的方法.
      FlyBehavior flyBehavior;//接口
      QuackBehavior quackBehavior;//接口
       public Duck(){}
       public abstract void display();
       public void swim(){
        //實現游泳的行為
        }
       public void performFly(){
            flyBehavior.fly();  -->由于是接口,會根據繼承類實現的方式,而調用相應的方法.
     }
     public void performQuack(){
          quackBehavior.quack();();
    }
 }
看看MallardDuck如何實現。
----->通過構造方法,生成'飛','叫'具體實現類的實例,從而指定'飛','叫'的具體屬性
 public class MallardDuck extends Duck{
       public MallardDuck {       
        flyBehavior = new FlyWithWings ();
        quackBehavior = new Quack(); 
      //因為MallardDuck 繼承了Duck,所有具有flyBehavior 與quackBehavior 實例變量}
    public void display(){
     //實現
   }
 }
 這樣就滿足了即可以飛,又可以叫,同時展現自己的顏色了。
這樣的設計我們可以看到是把flyBehavior ,quackBehavior 的實例化寫在子類了。我們還可以動態的來決定。
  我們只需在Duck中加上兩個方法。
 
在構造方法中對屬性進行賦值與用屬性的setter的區別:
構造方法中對屬性進行賦值:固定,不可變;
用屬性的setter,可以在實例化對象后,動態的變化,比較靈活。
 

  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(靜態工廠) -------------------------
(1)
在設計模式中,Factory Method也是比較簡單的一個,但應用非常廣泛,EJB,RMI,COM,CORBA,Swing中都可以看到此模式的影子,它是最重要的模式之一.在很多地方我們都會看到xxxFactory這樣命名的類.
(2)
基本概念:
FactoryMethod是一種創建性模式,它定義了一個創建對象的接口,但是卻讓子類來決定具體實例化哪一個類.
通常我們將Factory Method作為一種標準的創建對象的方法。
應用方面:
當一個類無法預料要創建哪種類的對象或是一個類需要由子類來指定創建的對象時我們就需要用到Factory Method 模式了.
-------------------------------- singelton(單例模式) --------------------------------
基本概念:
Singleton 是一種創建性模型,它用來確保只產生一個實例,并提供一個訪問它的全局訪問點.對一些類來說,保證只有一個實例是很重要的,比如有的時候,數據庫連接或 Socket 連接要受到一定的限制,必須保持同一時間只能有一個連接的存在.
運用:
在于使用static變量;
創建類對象,一般是在構造方法中,或用一個方法來創建類對象。在這里方法中,加對相應的判斷即可。
 
單態模式與共享模式的區別:
單態模式與共享模式都是讓類的實例是唯一的。
但單態模式的實現方式是:
在類的內部.即在構造方法中,或靜態的getInstace方法中,進行判斷,若實例存在,則直接返回,不進行創建;
共享模式的實現方式是:
每次要用到此實例時,先去此hashtable中獲取,若獲取為空,則生成實例,且將類的實例放在一人hashtable中,若獲取不為空,則直接用此實例。
 
 
 
(2)
實例一:
public class Singleton {  
  private static Singleton s; 
  public static Singleton getInstance() {
    if (s == null)
      s = new Singleton();
    return s;
  }
}
// 測試類
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運行結果是:
s1 is the same instance with s2
(3)
實例二:
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)基本概念:

觀察者模式屬于行為型模式,其意圖是定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都得到通知并被自動更新。

這一個模式的關鍵對象是目標(Subject)和觀察者(Observer)。一個目標可以有任意數目的依賴它的觀察者,一旦目標的狀態發生改變,所有的觀察者都得到通知,作為對這個通知的響應,每個觀察者都將查詢目標以使其狀態與目標的狀態同步。

適用場景:

觀察者模式用于存在一對多依賴關系的對象間,當被依賴者變化時,通知依賴者全部進行更新。因此,被依賴者,應該有添加/刪除依賴者的方法,且可以將添加的依賴者放到一個容器中;且有一個方法去通知依賴者進行更新。

(2)思想:

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

目標(subject)接口:
建立一個注冊觀察者對象的接口; public void attach(Observer o);
建立一個刪除觀察者對象的接口; public void detach(Observer o);
建立一個當目標狀態發生改變時,發布通知給觀察者對象的接口; public void notice();

觀察者(observer)接口:

建立一個當收到目標通知后的更新接口: public void update();
(3)實例:
老師又電話號碼,學生需要知道老師的電話號碼以便于在合時的時候撥打,在這樣的組合中,老師就是一個被觀察者(Subject),學生就是需要知道信息的觀察者,當老師的電話號碼發生改變時,學生得到通知,并更新相應的電話記錄。
具體實例如下:
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();    --關鍵
    }
    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{         -->可以只定義目標者,觀察者,另外的vector,只為了輸入結果.
    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();
    }
}
總結:Observer模式的最知名的應用是在MVC結構,Observer模式可以很好的應用在文檔和圖表程序的制作中。
------------------------------ 迭代器模式(Iterator) -------------------------------

(1)基本概念:

迭代器模式屬于行為型模式,其意圖是提供一種方法順序訪問一個聚合對象中得各個元素,而又不需要暴露該對象的內部表示。至少可以歷遍first,next,previous,last,isOver,或是歷遍選擇符合某種條件的子元素.

(2)結構:

由一個接口與一個實現類組成.
接口: 
主要是定義各歷遍的方法.
實現類: 
需要一個計算點private int current=0 ; 以及一個容器Vector,來存在原來的進行歷遍的一團東西;再對接口方法進行實現.

(3)實例:        

Iterator接口:
package iterator;
public interface Iterator{
/*
Item:即是集合中的各對象的類型.若為String,即把所有的ITEM改為String,若為其它自定義的類,則改為各自定義的類
的接口,或類. --->important.  
*/
    public Item first();
    public Item next();
    public boolean isDone();
    public Item currentItem();
}
Controller類實現了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類實現了Television接口。
package iterator;
import java.util.Vector;
public class HaierTV implements Television{     ---對象
    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);          --把這個VECTOR放到迭代器中構造方法中去
    }
}
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)
外觀模式屬于結構型模式,Facade模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
外觀模式的主要用途就是為子系統的復雜處理過程提供方便的調用方法,使得子系統更加容易被使用。
-->將復雜的過程包含在里面,提供一個簡單的應用接口即可.
(2)
例如在一個泡茶的過程中,需要作如下的工作:燒開水,準備茶葉,把茶葉放在被子里,把燒開的水放到茶杯中,只
有經過這些過程之后才能泡出好的茶葉來。這是一個常用的步驟,80%的泡茶步驟都是這個樣子的,可以把這些動作串
聯起來,形成一個整體的步驟.如下例的MakeACuppa(),使用了facade的模式,這樣在調用步方法時就比較方便。這便
是外觀模式,里面的細節被屏蔽掉了。
public class TeaCup{.....}
public class TeaBag{.....}
public class Water{.....}
public class FacadeCuppaMaker{
    private boolean TeaBagIsSteeped;
    public FacadeCuppaMaker(){
       System.out.println("FacadeCuppaMaker 準備好沖茶了");
    }
    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)
適配器模式的意圖是將一個已存在的類/接口進行復用,將其轉換/具體化成客戶希望的另外的一個類/接口。
(2)
如何實例復用:
將要進行復用的類,放到目標類的構造方法中,進行實例化,然后在目標類的相應方法中,進行調用,修改原來方法
中的參數,或添加相應的邏輯。即復用了已有類的原來方法。
要被復用的類:
public class Adaptee{
    public long getPower(long base,long exp){
       long result=1;
       for(int i=0;i<exp;i++)
           result*=base;
       return result;
    }
}
目標類:--也可直接實現,不用接口。
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);   ---修改原來方法中的參數,
    }
}
(3)
又如:
在SCM中添加的方法:
已有接口:
public boolean updateRecordStates(Double recordId,Double tableNameMapping,int state,boolean
subRecordUpdate) throws RemoteException;
已有實現類:
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;
實現類:
public boolean updateStatesAdapterForSelfPanel(Double recordId,Double tableNameMapping,int state)
throws RemoteException
{
 return this.updateRecordStates(recordId,tableNameMapping,state,false);
}
------------------------------ 代理模式(Proxy) -------------------------------
(1)
代理的好處:
--->是可以在間接訪問對象的同時,要其前或后,添加其它的邏輯代碼.
--->對原來邏輯進行添加其它邏輯,最終生成新的邏輯.即:對類的方法添加一些額外的邏輯,生成新的方法邏輯.
(2)
靜態代理: 
-->一個原類與一個代理類要一一對應。
-->兩者都實現共同的接口或繼承相同的抽象類;
-->只是在代理類中,實例化原類,在原類方法的前后添加新的邏輯。
如下:
抽象角色:
abstract public class Subject
{
    abstract public void request();
}
真實角色:
public class RealSubject extends Subject
{
       public void request()
       {
              System.out.println("From real subject.");
       }
}
代理角色:
public class ProxySubject extends Subject
{
    private RealSubject realSubject;  //以真實角色作為代理角色的屬性
       public ProxySubject()
       { realSubject=new RealSubject(); }
       public void request()  //與原方法名相同
       {
        preRequest();
        realSubject.request();  //此處執行真實對象的request方法
        postRequest();
      }
    private void preRequest()
    {
        //something you want to do before requesting
    }
    private void postRequest()
    {
        //something you want to do after requesting
    }
}
客戶端調用:
Subject sub=new ProxySubject();
Sub.request();
(3)
動態代理類
Java動態代理類位于Java.lang.reflect包下,一般主要涉及到以下兩個類:
1)
Interface InvocationHandler:該接口中僅定義了一個方法:invoke(Object obj,Method method, Object[] args)
。在實際使用時,第一個參數obj一般是指代理類,method是被代理的方法,args為該方法的參數數組。這個抽象方法
在代理類中動態實現。
2)
Proxy:該類即為動態代理類,其中主要包含以下內容:
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理類
的一個實例,返回后的代理類可以當作被代理類使用。
所謂Dynamic Proxy是這樣一種class:它是在運行時生成的class,在生成它時你必須提供一組interface給它,然后
該class就宣稱它實現了這些 interface。
3)
在使用動態代理類時,我們必須實現InvocationHandler接口,
public interface Subject
{
    public void request();
}
具體角色RealSubject:同上;
代理角色:
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
public class DynamicSubject implements InvocationHandler {
  private Object sub;
  public DynamicSubject(Object obj) {
    sub = obj;
  }
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("before calling " + method);
    method.invoke(sub,args);
    System.out.println("after calling " + method);
    return null;
  }
}
==>
method.invoke(sub,args);
其實就是調用被代理對象的將要被執行的方法,方法參數sub是實際的被代理對象,args為執行被代理對象相應操作所
需的參數。通過動態代理類,我們可以在調用之前或之后執行一些相關操作。
客戶端:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Client
{
    static public void main(String[] args) throws Throwable
    {
      RealSubject rs = new RealSubject();  //在這里指定被代理類
      InvocationHandler ds = new DynamicSubject(rs);  //初始化代理類
      Subject subject = (Subject) Proxy.newProxyInstance(rs.getClass().getClassLoader(),rs.getClass
().getInterfaces(),ds );
      subject.request();
}
5)
實例二:
package dynamicProxy;
public interface Work {
 public void startWork();
}
package dynamicProxy;
public class JasonWork implements Work {
 public void startWork() {
  System.out.println("jason start to work...");
 }
}
public interface Play {
 public void startPlay();
}
public class JasonPlay implements Play {
 public void startPlay() {
  System.out.println("jason start to play...");
 }
}
public class Test {
public static void main(String[] args) 
{
                JasonWork work=new JasonWork();
                InvocationHandler dynamicProxy=new DynamicProxy(work);
                Work jasonproxy=(Work)Proxy.newProxyInstance(work.getClass().getClassLoader(),
work.getClass().getInterfaces(), dynamicProxy);
                jasonproxy.startWork();
  JasonPlay play=new JasonPlay();
  InvocationHandler dynamicProxy=new DynamicProxy(play);
  Play jasonproxy=(Play)Proxy.newProxyInstance(play.getClass().getClassLoader(),
play.getClass().getInterfaces(), dynamicProxy);
  jasonproxy.startPlay();
 }
}
===>動態代理類,可以與任何類型的真實類(work/play),進行結合,進行動態的代理.
 
 
 
------------------------------ 狀態模式(state) -------------------------------
(1)
State模式定義:
不同的狀態,不同的行為; 或者說,每個狀態有著相應的行為.
適用場合:
State模式在實際使用中比較多,適合"狀態的切換".因為我們經常會使用If elseif else 進行狀態切換, 如果針對狀態的這樣判斷切換反復出現,我們就要聯想到是否可以采取State模式了.
-->適合于內部狀態,不斷循環變化的.
(2)
一個state,包括兩部分: 對象 + 對象內部的屬性(屬性接口+具體屬性)
一個對象,要有其屬性,以及其setter,getter.且設置好其初始狀態+一個調用顯示狀態的方法(里面就是狀態調用自身的顯示方法).
一個屬性接口,應該有一個執行的方法.
一個具體屬性,須包含對象進去,實現方法中,須設置對象下一個要顯示的屬性-->從而在對象下次調用方法時,其屬性值會變化.
 
狀態模式與觀察者模式的區別:
狀態模式,也跟觀察者模式一樣,是一對多的模式。但觀察者模式是“一”變了,所有的“多”也會更新。
狀態模式,強調的是:“多”是“一”的各個狀態,“一”的各個狀態,進行不斷的循環。
 
如何建立一與多的關系:
“多”,都是實現一個接口的。所以,在“一”的類中,聲明的是“多”的接口;若“多”中要建立與“一”的關系,只須直接在類中聲明“一”即可。
 
 
(3)
代碼:
public interface Color {
 public void show();
}
package state;
class Light
{
 Color color;
 public Color getColor() {
  return color;
 }
 public void setColor(Color color) {
  this.color = color;
 }
 
 public Light()
 {
  color=new RedColor(this);
 }
 
 public void showColor()
 {
  color.show();
 }
 
}
class RedColor implements Color
{
 Light light;
 public RedColor(Light light)
 {
  this.light=light;
 }
 
 public void show()
 {
 System.out.println("the color is red,the car must stop !");
 System.out.println("write down all logic shoud do this in this state.....");
  light.setColor(new GreenColor(light));
 }
}
class GreenColor implements Color
{
 Light light;
 public GreenColor(Light light)
 {
  this.light=light;
 }
 
 public void show()
 {
 System.out.println("the color is green,the car can run !");
 System.out.println("write down all logic shoud do this in this state.....");
  light.setColor(new YellowColor(light));
 }
}
class YellowColor implements Color
{
 Light light;
 public YellowColor(Light light)
 {
  this.light=light;
 }
 
 public void show()
 {
 System.out.println("the color is yellow,the car shoud stop !");
 System.out.println("write down all logic shoud do this in this state.....");
  light.setColor(new RedColor(light));
 }
}
public class CarLight {
 public static void main(String[] args) {
  Light light=new Light();
  
  //初始調用為紅燈
  light.showColor();
  //再調用為綠燈
  light.showColor();
  //再調用為黃燈
  light.showColor();
  //不斷調用,不斷循環.  
 }
}
 
 
 
------------------------------ 享元模式(Flyweight) -------------------------------
(1)
主要用于創建對象時,運用共享技術,減少對象對內存的占用.一個提高程序效率和性能的模式,會大大加快程序的運
行速度.
就是說在一個系統中如果有多個相同的對象,那么只共享一份就可以了,不必每個都去實例化一個對象。
Flyweight(享元)模式中常出現Factory模式。Flyweight的內部狀態是用來共享的,Flyweight factory負責維護一個對
象存儲池(Flyweight Pool)來存放內部狀態的對象。
Flyweight的關鍵思路,在于:
新建對象時:
先到hashtable中進行獲取-->判斷取得對象是否為空-->若是,則新建此對象,且放回hashtable -->若存在,則共享原來
的對象.
(2)
實例: (與靜態工廠模式進行對比)
public interface Car {
 public void showCarName();
}
class BMWCar implements Car
{
 public void showCarName()
 {
  System.out.println("this is the BMWCar .");
 }
}
class FordCar implements Car
{
 public void showCarName()
 {
  System.out.println("this is the FordCar .");
 }
}
class CarFactory
{
 public static Car car;
 public static Car getCar(String name)
 {
  if("BMW".equals(name))
  {
   car = new BMWCar();
  }
  if("Ford".equals(name))
  {
   car =  new FordCar();
  }
  return car;
 }
}
class CarFlyWeightFactory
{
    public  Car car;
    private Hashtable<String,Car> carPool=new Hashtable<String,Car>();
 public  Car getCar(String name)
 {
  if("BMW".equals(name))
  {
   car=carPool.get(name);
   if(car==null)
   {
    car=new BMWCar();
    carPool.put(name, car);
   }
  }
  
  if("Ford".equals(name))
  {
   car=carPool.get(name);
   if(car==null)
   {
    car=new FordCar();
    carPool.put(name, car);
   }
  }
  return car;
 }
        public int getNumber(){ return carPool.getSize(); }
}

public class Test {
 public static void main(String[] args) {
  CarFlyWeightFactory carFlyWeightFactory=new CarFlyWeightFactory();
  Car carf1=carFlyWeightFactory.getCar("Ford");
  carf1.showCarName();
  Car carf2=carFlyWeightFactory.getCar("Ford");
  carf2.showCarName();
  if(carf1==carf2)
  {
   System.out.println("同一部車來的");
  }
  else
  {
   System.out.println("不同一部車來的");
  }
  System.out.println("車的數量是:"+carFlyWeightFactory.getNumber());
 }
}
輸出:
this is the FordCar .
this is the FordCar .
同一部車來的
 
---------------------- 職責鏈模式(Chain of Responsibility) -----------------------
(1)
Chain of Responsibility職責鏈模式:
為了避免請求的發送者和接收者之間的耦合關系,使多個接受對象都有機會處理請求。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它為止。
-->
要沿著鏈轉發請求,并保證接受者為隱式的,每個鏈上的對象都有一致的處理請求和訪問鏈上后繼者的接口(即如下實例中,在自己方法中再調用一次相同的方法)。
(2)
public class Boy {
 
 private boolean hasCar; // 是否有車
 private boolean hasHouse; // 是否有房
 private boolean hasResponsibility; // 是否有責任心
 public Boy() {
 }
 public Boy(boolean hasCar, boolean hasHouse, boolean hasResponsibility) {
  this.hasCar = hasCar;
  this.hasHouse = hasHouse;
  this.hasResponsibility = hasResponsibility;
 }
 public boolean isHasCar() {
  return hasCar;
 }
 public void setHasCar(boolean hasCar) {
  this.hasCar = hasCar;
 }
 public boolean isHasHouse() {
  return hasHouse;
 }
 public void setHasHouse(boolean hasHouse) {
  this.hasHouse = hasHouse;
 }
 public boolean isHasResponsibility() {
  return hasResponsibility;
 }
 public void setHasResponsibility(boolean hasResponsibility) {
  this.hasResponsibility = hasResponsibility;
 }
}
public interface Handler {
  public void handleRequest(Boy boy);
}
public class HouseHandler implements Handler {
 
 private Handler handler;
 public HouseHandler(Handler handler) {
  this.handler = handler;
 }
 public Handler getHandler() {
  return handler;
 }
 public void setHandler(Handler handler) {
  this.handler = handler;
 }
 public void handleRequest(Boy boy) {
  if (boy.isHasHouse()) {
   System.out.println("沒想到吧,我還有房子");
  } else {
   System.out.println("我也沒有房");
   handler.handleRequest(boy);
  }
 }
}
public class CarHandler implements Handler {
 private Handler handler;
 public CarHandler(Handler handler) {
  this.handler = handler;
 }
 public Handler getHandler() {
  return handler;
 }
 public void setHandler(Handler handler) {
  this.handler = handler;
 }
 public void handleRequest(Boy boy) {
  if (boy.isHasCar()) {
   System.out.println("呵呵,我有輛車");
  } else {
   System.out.println("我沒有車");
   handler.handleRequest(boy);
  }
 }
}
public class ResponsibilityHandler implements Handler {
 private Handler handler;
 public ResponsibilityHandler(Handler handler) {
  this.handler = handler;
 }
 public Handler getHandler() {
  return handler;
 }
 public void setHandler(Handler handler) {
  this.handler = handler;
 }
 public void handleRequest(Boy boy) {
  if (boy.isHasResponsibility()) {
   System.out.println("我只有一顆帶Responsibility的心");
  } else {
   System.out.println("更沒有責任心");
   handler.handleRequest(boy);
  }
 }
}
public class Girl {
 
 public static void main(String[] args) {
  // 這個boy沒有車,也沒有房,不過很有責任心
  Boy boy = new Boy(false, false, true);
                // 也可以使用setHanlder方法
  Handler handler = new CarHandler(new HouseHandler(
    new ResponsibilityHandler(null)));
  handler.handleRequest(boy);
 }
}
==>
如何實例使請求沿著鏈在各接受對象中傳遞,當沒被第一個接受對象接受時,會傳遞給第二個對象,若被第一個對象接受了,則不傳遞下去:
1.各具體的接受對象采用這樣的構造方法:
public CarHandler(Handler handler) { this.handler = handler; }
2.各具體的接受對象實現接口的方法handleRequest()中.在調用時,若被接受,則執行true的內容,若不被接受,則執行false的內容,并繼續調用再調用handleRequest()方法.
3.在最后的測試類中,生成具體的handler時,用多層包含的形式.這樣,在調用了上一層car的方法后,會調用house的相應方法,最后再調用ResponsibilityHandler的方法.
==>前兩個handler是采用了有參數的構造方法,最后一個是采用了為NULL的構造方法

------------------------------ 備忘錄模式(Memento) -------------------------------
(1)
備忘錄模式屬于行為型模式,其意圖是在不破壞封裝性的前提下,捕獲一個對象的內部狀態,并在該對象之外保存這
個狀態,這樣以后就可以將對象恢復到原先保存的狀態。
(2)
實例如下:
有一個對象Employee.除了屬性外,還需要一個保存,還原狀態的方法.
有一個對象Memento,用來記錄Employee每一個時刻的狀態,
CareTaker,用來保存,拿回Memento.需要一個保存,還原狀態的方法.->需要一個指針,一個容器.
package memento;
public class Memento{
    String name;
    int age;
    public Memento(String name,int age){
       this.name = name;
       this.age = age;
    }
}
Employee模式:
package memento;
public class Employee{
    private String name;
    private int age;
    public Employee(String aName,int aAge){
       name = aName;
       age = aAge;
    }
    public void setName(String aName){
       name = aName;
    }
    public void setAge(int aAge){
       age = aAge;
    }
    public Memento  saveMemento(){
       return new Memento(name,age);
    }
    public void restoreMemento(Memento memento){
       age = memento.age;
       name = memento.name;
    }
    public int getAge(){
       return age;
    }
    public String getName(){
       return name;
    }
}
CareTaker代碼:
package memento;
import java.util.Vector;
public class CareTaker{
    private Vector v;
    private int  current;
    public CareTaker(){
       current = -1;
       v = new Vector();
    }
    public void setMemento(Memento mem){
       current ++;
       v.add(mem);
    }
    public Memento getMemento(){
       if(current>0){
           current --;
           return(Memento) v.get(current);
       }
       return null;
    }
}
Client代碼:
package memento;
public class Client{
    public static void show(Employee e){
       System.out.println("-----------------------------------");
       System.out.println("Name:"+e.getName());
       System.out.println("Age:" + e.getAge());
       System.out.println("-----------------------------------");
    }
    public static void main(String[] args){
       Employee e = new Employee("lili",25);
       CareTaker ct = new CareTaker();
       show(e);
       ct.setMemento(e.saveMemento());
       e.setName("litianli");
       show(e);
       ct.setMemento(e.saveMemento());
       e.setAge(45);
       show(e);
       ct.setMemento(e.saveMemento());
       //restore
       e.restoreMemento(ct.getMemento());
       show(e);
       e.restoreMemento(ct.getMemento());
       show(e);
    }
}
 
 
 
 
本文出自 “Changes we need ! ” 博客,請務必保留此出處http://shenzhenchufa.blog.51cto.com/730213/161581

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品美女无圣光视频| 国产精品视频久久| 精品亚洲精品福利线在观看| 亚洲欧美国产精品| 91精品国产精品| 国产欧美精品va在线观看| 青青久久aⅴ北条麻妃| 欧美放荡办公室videos4k| 欧美色道久久88综合亚洲精品| 中文字幕精品一区久久久久| 亚洲第一综合天堂另类专| 日韩专区中文字幕| 亚洲午夜精品久久久久久性色| 在线观看久久av| 欧美第一淫aaasss性| 欧美激情亚洲精品| 久久久久久久一区二区| 久久九九有精品国产23| 欧美国产第一页| 在线看日韩av| 欧美国产视频一区二区| 日韩视频永久免费观看| 555www成人网| 91国产视频在线播放| 国产精品成人在线| 日韩成人在线电影网| 操人视频在线观看欧美| 国产精品第一页在线| 亚洲最大的成人网| www.国产精品一二区| 国产综合香蕉五月婷在线| 热久久这里只有| 91大神福利视频在线| 中文字幕在线看视频国产欧美在线看完整| 精品国产91久久久| 日韩网站免费观看| 欧美日韩国产丝袜另类| 欧美成人午夜激情在线| 亚洲精品第一国产综合精品| 国产主播精品在线| 日韩欧美在线国产| 国产精品久久久久福利| 97视频免费在线观看| 国产精品十八以下禁看| 欧美国产视频日韩| 久久久久免费精品国产| 国产精品色视频| 一区二区三区日韩在线| 精品日韩中文字幕| 欧美高清无遮挡| 成人久久一区二区三区| 日韩av电影在线播放| 国产在线观看不卡| 欧美老女人性生活| 国内自拍欧美激情| 日韩av影片在线观看| 欧美性生交xxxxx久久久| 91成人在线观看国产| 欧美大秀在线观看| 国产精自产拍久久久久久| 欧美成人激情视频免费观看| 久久亚洲一区二区三区四区五区高| 国产深夜精品福利| 欧美丝袜一区二区三区| 亚洲一区亚洲二区亚洲三区| 日韩电影在线观看免费| 欧美性xxxx极品hd欧美风情| 亚洲自拍偷拍第一页| 久久久久久网站| 国产精品嫩草视频| 日本视频久久久| 久久久久久久久国产精品| 欧美激情伊人电影| 国产aⅴ夜夜欢一区二区三区| 欧美第一黄网免费网站| 国产91精品最新在线播放| 97视频在线观看亚洲| 亚洲人成网站免费播放| 亚洲女人被黑人巨大进入al| 亚洲91av视频| 日本午夜精品理论片a级appf发布| 亚洲综合小说区| 欧美日韩国产精品一区二区不卡中文| 欧美午夜性色大片在线观看| 18一19gay欧美视频网站| 91精品一区二区| 成人激情电影一区二区| 国产一区二区免费| 午夜精品视频网站| 午夜精品国产精品大乳美女| 在线观看久久久久久| 欧美性猛交xxx| 亚洲成人久久电影| 国产精品日韩在线| 欧美怡春院一区二区三区| 精品动漫一区二区三区| 欧洲精品久久久| 亚洲无限乱码一二三四麻| 久久这里只有精品99| 久久精品国产成人| 午夜精品一区二区三区在线视| 国产精品91在线观看| 国产一区二区在线播放| 亚洲黄页网在线观看| 日本国产欧美一区二区三区| 欧美整片在线观看| 中文字幕一区二区三区电影| 日本精品久久久久久久| 国产在线观看精品一区二区三区| 2019中文字幕免费视频| 国产精品三级在线| 最近2019免费中文字幕视频三| 色哟哟亚洲精品一区二区| 91av在线播放视频| 91国内在线视频| 丝袜情趣国产精品| 国产精品高潮呻吟久久av野狼| 日韩av大片在线| 欧美高清videos高潮hd| 最近2019免费中文字幕视频三| 国产精品综合不卡av| 国产成人精品国内自产拍免费看| 色偷偷偷亚洲综合网另类| 国产精品夫妻激情| 欧美一区二区三区四区在线| 久久九九热免费视频| 日韩欧美在线第一页| 国产精品69精品一区二区三区| 国产精品一区二区久久精品| 日韩欧美成人免费视频| 91手机视频在线观看| 91视频国产一区| 国产黑人绿帽在线第一区| 亚洲人成欧美中文字幕| 亚洲高清在线观看| 久久久精品免费视频| 这里只有精品在线观看| 国产香蕉97碰碰久久人人| 日本高清视频精品| 日韩成人在线视频网站| 中文字幕最新精品| 欧美大尺度在线观看| 国产精品一区二区久久久| 久久久国产一区二区| 国产成人综合久久| 亚洲女人天堂av| 最近2019中文字幕第三页视频| 国产精品美腿一区在线看| 日韩电影大片中文字幕| 免费99精品国产自在在线| 九色91av视频| 国产欧美一区二区| 日韩在线视频导航| wwwwwwww亚洲| 日韩中文在线中文网在线观看| 欧美性少妇18aaaa视频| 2020国产精品视频| 中文字幕日韩精品在线观看| 精品女厕一区二区三区| 亚洲精品国精品久久99热一| 精品国产一区二区三区久久狼黑人| 色哟哟网站入口亚洲精品| 久久久久久有精品国产| 欧美在线视频免费播放|