JAVA設計模式

1、什麼是設計模式                                                                                                                 

  設計模式(Design pattern)是一套被反覆使用、多數人知曉的、通過分類編目的、代碼設計經驗的總結。使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 毫無疑問,設計模式於己於他人於系統都是多贏的,設計模式使代碼編制真正工程化,設計模式是軟件工程的基石,如同大廈的一塊塊磚石同樣。項目中合理的運用設計模式能夠完美的解決不少問題,每種模式在如今中都有相應的原理來與之對應,每個模式描述了一個在咱們周圍不斷重複發生的問題,以及該問題的核心解決方案,這也是它能被普遍應用的緣由。簡單說:程序員

模式:在某些場景下,針對某類問題的某種通用的解決方案。算法

  • 場景:項目所在的環境
  • 問題:約束條件,項目目標等
  • 解決方案:通用、可複用的設計,解決約束達到目標。

2、設計模式的分類

 整體來講設計模式分爲三大類:編程

  • 建立型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
  • 結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
  • 行爲型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。
  • 其實還有兩類:併發型模式和線程池模式。

用一個圖片來總體描述一下:設計模式

3、設計模式的六大原則

  • 總原則:開閉原則(Open Close Principle)
    • 開閉原則就是說對擴展開放,對修改關閉。在程序須要進行拓展的時候,不能去修改原有的代碼,而是要擴展原有代碼,實現一個熱插拔的效果。因此一句話歸納就是:爲了使程序的擴展性好,易於維護和升級。想要達到這樣的效果,咱們須要使用接口和抽象類等,後面的具體設計中咱們會提到這點。
  • 單一責任原則
    • 不要存在多於一個致使類變動的緣由,也就是說每一個類應該實現單一的職責,如若否則,就應該把類拆分。
  • 里氏替換原則(Liskov Substitution Principle)
    • 里氏代換原則(Liskov Substitution Principle LSP)面向對象設計的基本原則之一。 里氏代換原則中說,任何基類能夠出現的地方,子類必定能夠出現。 LSP是繼承複用的基石,只有當衍生類能夠替換掉基類,軟件單位的功能不受到影響時,基類才能真正被複用,而衍生類也可以在基類的基礎上增長新的行爲。里氏代換原則是對「開-閉」原則的補充。實現「開-閉」原則的關鍵步驟就是抽象化。而基類與子類的繼承關係就是抽象化的具體實現,因此里氏代換原則是對實現抽象化的具體步驟的規範。
    • 歷史替換原則中,子類對父類的方法儘可能不要重寫和重載。由於父類表明了定義好的結構,經過這個規範的接口與外界交互,子類不該該隨便破壞它
  • 依賴倒轉原則(Dependence Inversion Principle)
    • 這個是開閉原則的基礎,具體內容:面向接口編程,依賴於抽象而不依賴於具體。寫代碼時用到具體類時,不與具體類交互,而與具體類的上層接口交互。
  • 接口隔離原則(Interface Segregation Principle)
    • 每一個接口中不存在子類用不到卻必須實現的方法,若是否則,就要將接口拆分。使用多個隔離的接口,比使用單個接口(多個接口方法集合到一個的接口)要好。
  • 迪米特法則(最少知道原則)(Demeter Principle)
    • 一個類對本身依賴的類知道的越少越好。也就是說不管被依賴的類多麼複雜,都應該將邏輯封裝在方法的內部,經過public方法提供給外部。這樣當被依賴的類變化時,才能最小的影響該類。
    • 最少知道原則的另外一個表達方式是:只與直接的朋友通訊。類之間只要有耦合關係,就叫朋友關係。耦合分爲依賴、關聯、聚合、組合等。咱們稱出現爲成員變量、方法參數、方法返回值中的類爲直接朋友。局部變量、臨時變量則不是直接的朋友。咱們要求陌生的類不要做爲局部變量出如今類中。
  • 合成複用原則(Composite Reuse Principle)
    • 原則是儘可能首先使用合成/聚合的方式,而不是使用繼承。

4、各分類中模式的關鍵點

  • 單例模式:某個類只能有一個實例,提供一個全局的訪問點。
  • 簡單模式:一個工廠類根據傳入的參量決定建立出那一種產品類的實例。
  • 工廠模式:定義一個建立對象的接口,讓子類決定實例化那個類。
  • 抽象工廠:建立相關或依賴對象的家族,而無需明確指定具體類。
  • 抽象工廠:建立相關或依賴對象的家族,而無需明確指定具體類。
  • 建造者模式:封裝一個複雜對象的構建過程,並能夠按步驟構造。
  • 原型模式:經過複製現有的實例來建立新的實例。
  • 適配器模式:將一個類的方法接口轉換成客戶但願的另一個接口。
  • 組合模式:將對象組合成樹形結構以表示「」部分-總體「」的層次結構。
  • 裝飾模式:動態的給對象添加新的功能。
  • 代理模式:爲其餘對象提供一個代理以便控制這個對象的訪問。
  • 亨元(蠅量)模式:經過共享技術來有效的支持大量細粒度的對象。
  • 外觀模式:對外提供一個統一的方法,來訪問子系統中的一羣接口。
  • 橋接模式:將抽象部分和它的實現部分分離,使它們均可以獨立的變化。
  • 模板模式:定義一個算法結構,而將一些步驟延遲到子類實現。
  • 解釋器模式:給定一個語言,定義它的文法的一種表示,並定義一個解釋器。
  • 策略模式:定義一系列算法,把他們封裝起來,而且使它們能夠相互替換。
  • 狀態模式:容許一個對象在其對象內部狀態改變時改變它的行爲。
  • 觀察者模式:對象間的一對多的依賴關係。
  • 備忘錄模式:在不破壞封裝的前提下,保持對象的內部狀態。
  • 中介者模式:用一箇中介對象來封裝一系列的對象交互。
  • 命令模式:將命令請求封裝爲一個對象,使得能夠用不一樣的請求來進行參數化。
  • 訪問者模式:在不改變數據結構的前提下,增長做用於一組對象元素的新功能。
  • 責任鏈模式:將請求的發送者和接收者解耦,使的多個對象都有處理這個請求的機會。
  • 迭代器模式:一種遍歷訪問聚合對象中各個元素的方法,不暴露該對象的內部結構。

5、Java的23中設計模式

  • 單例模式 安全

    • 單例模式,它的定義就是確保某一個類只有一個實例,而且提供一個全局訪問點。
    • 單例模式具有典型的3個特色:一、只有一個實例。 二、自我實例化。 三、提供全局訪問點。
    • 所以當系統中只須要一個實例對象或者系統中只容許一個公共訪問點,除了這個公共訪問點外,不能經過其餘訪問點訪問該實例時,可使用單例模式。
    • 單例模式的主要優勢就是節約系統資源、提升了系統效率,同時也可以嚴格控制客戶對它的訪問。也許就是由於系統中只有一個實例,這樣就致使了單例類的職責太重,違背了「單一職責原則」,同時也沒有抽象類,因此擴展起來有必定的困難。
    • 主要角色
      • 單例類:包含一個實例且能自行建立這個實例的類。
      • 訪問類:使用單例的類。
    • 其UML結構圖很是簡單,就只有一個類,以下圖:
    • 單例模式的實現
      • 懶漢式單例
        public class LazySingleton {
            
            private static volatile LazySingleton instance = null;        //保證 instance 在全部線程中同步
            
            private LazySingleton() {}                                    //private 避免類在外部被實例化
            
            public static synchronized LazySingleton getInstance() {
                //getInstance 方法前加同步
                if(instance == null) {
                    instance = new LazySingleton();
                }
                return instance;
            }
        }
      • 餓漢式單例
        public class HungrySingleton {
            
            private static final HungrySingleton instance = new HungrySingleton();
            
            private HungrySingleton(){}
            
            public static HungrySingleton getInstance() {
                return instance;
            }
        }
  • 工廠方法模式
    • 做爲抽象工廠模式的孿生兄弟,工廠方法模式定義了一個建立對象的接口,但由子類決定要實例化的類是哪個,也就是說工廠方法模式讓實例化推遲到子類。
    • 工廠方法模式很是符合「開閉原則」,當須要增長一個新的產品時,咱們只須要增長一個具體的產品類和與之對應的具體工廠便可,無須修改原有系統。
    • 同時在工廠方法模式中用戶只須要知道生產產品的具體工廠便可,無須關係產品的建立過程,甚至連具體的產品類名稱都不須要知道。
    • 主要角色
      • ·抽象工廠(Abstract Factory):提供了建立產品的接口,調用者經過它訪問具體工廠的工廠方法 newProduct() 來建立產品。
      • 具體工廠(ConcreteFactory):主要是實現抽象工廠中的抽象方法,完成具體產品的建立。
      • 抽象產品(Product):定義了產品的規範,描述了產品的主要特性和功能。
      • 具體產品(ConcreteProduct):實現了抽象產品角色所定義的接口,由具體工廠來建立,它同具體工廠之間一一對應。
    • 雖然他很好的符合了「開閉原則」,可是因爲每新增一個新產品時就須要增長兩個類,這樣勢必會致使系統的複雜度增長。其UML結構圖
    • 模式的實現:
      public interface Product {
          public void  show();
      }
      
      public class ConcreteProduct1 implements Product {
      
          public void show() {
              System.out.println("具體產品1顯示....");
          }
      }
      
      public class ConcreteProduct2 implements Product {
      
          public void show() {
              System.out.println("具體產品1顯示....");
          }
      }
      
      public interface AbstractFactory {
          
          public Product newProduct();
      }
      
      public class ConcreteFactory1 implements AbstractFactory {
      
          public Product newProduct() {
              System.out.println("具體工廠1生成-->具體產品1...");
              return new ConcreteProduct1();
          }
      }
      
      public class ConcreteFactory2 implements AbstractFactory {
      
          public Product newProduct() {
              System.out.println("具體工廠2生成-->具體產品2...");
              return new ConcreteProduct2();
          }
      }
      
      public class AbstractFactoryTest {
          
          public static void main(String[] args) {
              try {
                  Class<?> c = Class.forName("com.lynn.learning.designPattern.factoryMethod.ConcreteFactory2");
                  AbstractFactory af = (AbstractFactory) c.newInstance();
                  Product a = af.newProduct();
                  a.show();
              } catch(Exception e) {
                  e.printStackTrace();
              }
          }
      }
  • 抽象工廠模
    • 所謂抽象工廠模式就是提供一個接口,用於建立相關或者依賴對象的家族,而不須要明確指定具體類。
    • 他容許客戶端使用抽象的接口來建立一組相關的產品,而不須要關係實際產出的具體產品是什麼。這樣一來,客戶就能夠從具體的產品中被解耦。
    • 它的優勢是隔離了具體類的生成,使得客戶端不須要知道什麼被建立了,而缺點就在於新增新的行爲會比較麻煩,由於當添加一個新的產品對象時,須要更加須要更改接口及其下全部子類。
    • 主要角色:
      • 抽象工廠(Abstract Factory):提供了建立產品的接口,它包含多個建立產品的方法 newProduct(),能夠建立多個不一樣等級的產品。
      • 具體工廠(Concrete Factory):主要是實現抽象工廠中的多個抽象方法,完成具體產品的建立。
      • 抽象產品(Product):定義了產品的規範,描述了產品的主要特性和功能,抽象工廠模式有多個抽象產品。
      • 具體產品(ConcreteProduct):實現了抽象產品角色所定義的接口,由具體工廠來建立,它 同具體工廠之間是多對一的關係。
    • 其UML結構圖以下:
    • 模式實現:
      public interface Animal {
          public void show();
      }
      
      public class Cattle implements Animal {
      
          JScrollPane sp;
          
          JFrame jf = new JFrame("抽象工廠模式測試");
          
          public Cattle() {
              Container contentPane=jf.getContentPane();
              JPanel p1 = new JPanel();
              p1.setLayout(new GridLayout(1,1));
              p1.setBorder(BorderFactory.createTitledBorder("動物:牛"));
              sp = new JScrollPane(p1);
              contentPane.add(sp, BorderLayout.CENTER);
              JLabel l1 = new JLabel(new ImageIcon("src/com/lynn/learning/designPattern/abstractFactory/A_Cattle.jpg"));
              p1.add(l1);       
              jf.pack();       
              jf.setVisible(false);
              jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用戶點擊窗口關閉 
          }
          
          public void show() {
              jf.setVisible(true);
          }
      }
      
      public class Horse implements Animal {
          JScrollPane sp;
          
          JFrame jf = new JFrame("抽象工廠模式測試");
          
          public Horse() {
              Container contentPane = jf.getContentPane();
              JPanel p1 = new JPanel();
              p1.setLayout(new GridLayout(1,1));
              p1.setBorder(BorderFactory.createTitledBorder("動物:馬"));
              sp = new JScrollPane(p1);
              contentPane.add(sp, BorderLayout.CENTER);
              JLabel l1 = new JLabel(new ImageIcon("src/com/lynn/learning/designPattern/abstractFactory/A_Horse.jpg"));
              p1.add(l1);       
              jf.pack();       
              jf.setVisible(false);
              jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用戶點擊窗口關閉 
          }
          
          public void show() {
              jf.setVisible(true);
          }
      }
      
      public interface Farm {
          public Animal newAnimal();
          public Plant newPlant();
      }
      
      public class Fruitage implements Plant {
      
          JScrollPane sp;
          JFrame jf = new JFrame("抽象工廠模式測試");
          
          public Fruitage() {
              Container contentPane = jf.getContentPane();
              JPanel p1 = new JPanel();
              p1.setLayout(new GridLayout(1,1));
              p1.setBorder(BorderFactory.createTitledBorder("植物:水果"));
              sp = new JScrollPane(p1);
              contentPane.add(sp, BorderLayout.CENTER);
              JLabel l1 = new JLabel(new ImageIcon("src/com/lynn/learning/designPattern/abstractFactory/P_Vegetables.jpg"));
              p1.add(l1);       
              jf.pack();       
              jf.setVisible(false);
              jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用戶點擊窗口關閉 
          }
          
          public void show() {
              jf.setVisible(true);
          }
      }
      
      public class Vegetables implements Plant {
      
          JScrollPane sp;
          
          JFrame jf = new JFrame("抽象工廠模式測試");
          
          public Vegetables() {
              Container contentPane = jf.getContentPane();
              JPanel p1 = new JPanel();
              p1.setLayout(new GridLayout(1, 1));
              p1.setBorder(BorderFactory.createTitledBorder("植物:蔬菜"));
              sp = new JScrollPane(p1);
              contentPane.add(sp, BorderLayout.CENTER);
              JLabel l1 = new JLabel(new ImageIcon("src/com/lynn/learning/designPattern/abstractFactory/P_Vegetables.jpg"));
              p1.add(l1);       
              jf.pack();       
              jf.setVisible(false);
              jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用戶點擊窗口關閉 
          }
          
          public void show() {
              jf.setVisible(true);
          }
      }
      
      public class SGfarm implements Farm {
      
          public Animal newAnimal() {
              System.out.println("新牛出生!");
              return new Cattle();
          }
      
          public Plant newPlant() {
              System.out.println("蔬菜長成!");
              return new Vegetables();
          }
      }
      
      public class SRfarm implements Farm {
      
          public Animal newAnimal() {
              System.out.println("新馬出生!");
              return new Horse();
          }
      
          public Plant newPlant() {
              System.out.println("水果長成!");
              return new Fruitage();
          }
      }
      
      public class FarmTest {
          
          public static void main(String[] args) {
              try {
                  Class<?> c = Class.forName("com.lynn.learning.designPattern.abstractFactory.SGfarm");
                  Farm f = (Farm) c.newInstance();
                  Animal a = f.newAnimal();
                  Plant p = f.newPlant();
                  a.show();
                  p.show();
              } catch(Exception e) {
                  e.printStackTrace();
              }
          }
      }
  • 建造者模式
    • 對於建造者模式而已,它主要是將一個複雜對象的構建與表示分離,使得一樣的構建過程能夠建立不一樣的表示。適用於那些產品對象的內部結構比較複雜。
    • 建造者模式將複雜產品的構建過程封裝分解在不一樣的方法中,使得建立過程很是清晰,可以讓咱們更加精確的控制複雜產品對象的建立過程,同時它隔離了複雜產品對象的建立和使用,使得相同的建立過程可以建立不一樣的產品。
    • 可是若是某個產品的內部結構過於複雜,將會致使整個系統變得很是龐大,不利於控制,同時若幾個產品之間存在較大的差別,則不適用建造者模式,畢竟這個世界上存在相同點大的兩個產品並非不少,因此它的使用範圍有限。
    • 優勢:
      • 各個具體的建造者相互獨立,有利於系統的擴展。
      • 客戶端沒必要知道產品內部組成的細節,便於控制細節風險
    • 缺點:
      • 產品的組成部分必須相同,這限制了其使用範圍。
      • 若是產品的內部變化複雜,該模式會增長不少的建造者類。
    • 主要角色:
      • 產品角色(Product):它是包含多個組成部件的複雜對象,由具體建造者來建立其各個滅部件。
      • 抽象建造者(Builder):它是一個包含建立產品各個子部件的抽象方法的接口,一般還包含一個返回複雜產品的方法 getResult()。
      • 具體建造者(Concrete Builder):實現 Builder 接口,完成複雜產品的各個部件的具體建立方法。
      • 指揮者(Director):它調用建造者對象中的部件構造與裝配方法完成複雜對象的建立,在指揮者中不涉及具體產品的信息。
    • 其UML結構圖:
    • 模式實現:
  • 原型模式
    • 在咱們應用程序可能有某些對象的結構比較複雜,可是咱們又須要頻繁的使用它們,若是這個時候咱們來不斷的新建這個對象勢必會大大損耗系統內存的,這個時候咱們須要使用原型模式來對這個結構複雜又要頻繁使用的對象進行克隆。因此原型模式就是用原型實例指定建立對象的種類,而且經過複製這些原型建立新的對象。
    • 它主要應用與那些建立新對象的成本過大時。它的主要優勢就是簡化了新對象的建立過程,提升了效率,同時原型模式提供了簡化的建立結構。
    • 主要角色:
      • 抽象原型類:規定了具體原型對象必須實現的接口。
      • 具體原型類:實現抽象原型類的 clone() 方法,它是可被複制的對象。
      • 訪問類:使用具體原型類中的 clone() 方法來複制新的對象。
    • UML結構圖:
    • 模式實現:
      public interface Shape extends Cloneable {
          public Object clone();            //拷貝
          public void countArea();        //計算面積
      }
      
      public class Square implements Shape {
         
          private Scanner input;
      
          public Object clone() {
              Square b = null;
              try {
                  b = (Square)super.clone();
              } catch(CloneNotSupportedException e) {
                  System.out.println("拷貝正方形失敗!");
              }
              return b;
          }
          
          public void countArea() {
              int a = 0;
              System.out.print("這是一個正方形,請輸入它的邊長:");
              input = new Scanner(System.in);
              a=input.nextInt();
              System.out.print("該正方形的面積=" + a * a + "\n");
          }
      }
      
      public class Circle implements Shape {
      
          private Scanner input;
      
          public Object clone() {
              Circle w = null;
              try {
                  w = (Circle)super.clone();
              } catch(CloneNotSupportedException e) {
                  System.out.println("拷貝圓失敗!");
              }
              return w;
          }
          
          public void countArea() {
              int r=0;
              System.out.print("這是一個圓,請輸入圓的半徑:");
              input = new Scanner(System.in);
              r = input.nextInt();
              System.out.println("該圓的面積=" + 3.1415 * r * r + "\n");
          }
      
      }
      
      public class ProtoTypeManager {
          private HashMap<String, Shape> ht = new HashMap<String,Shape>(); 
          
          public ProtoTypeManager() {
              ht.put("Circle", new Circle());
              ht.put("Square", new Square());
          } 
          
          public void addshape(String key, Shape obj) {
              ht.put(key, obj);
          }
          
          public Shape getShape(String key) {
              Shape temp = ht.get(key);
              return (Shape) temp.clone();
          }
      }
      
      public class ProtoTypeShape {
          public static void main(String[] args) {
              ProtoTypeManager pm = new ProtoTypeManager();    
              Shape obj1 = (Circle)pm.getShape("Circle");
              obj1.countArea();          
              Shape obj2 = (Shape)pm.getShape("Square");
              obj2.countArea();     
          }
      }
  • 適配器模式(Adapter)
    • 在咱們的應用程序中咱們可能須要將兩個不一樣接口的類來進行通訊,在不修改這兩個的前提下咱們可能會須要某個中間件來完成這個銜接的過程。這個中間件就是適配器。
    • 所謂適配器模式就是將一個類的接口,轉換成客戶指望的另外一個接口。它可讓本來兩個不兼容的接口可以無縫完成對接。
    • 做爲中間件的適配器將目標類和適配者解耦,增長了類的透明性和可複用性。
    • 主要角色
      • 目標(Target)接口:當前系統業務所期待的接口,它能夠是抽象類或接口。
      • 適配者(Adaptee)類:它是被訪問和適配的現存組件庫中的組件接口。
      • 適配器(Adapter)類:它是一個轉換器,經過繼承或引用適配者的對象,把適配者接口轉換成目標接口,讓客戶按目標接口的格式訪問適配者。
    • 優勢
      • 客戶端經過適配器能夠透明地調用目標接口。
      • 複用了現存的類,程序員不須要修改原有代碼而重用現有的適配者類。
      • 將目標類和適配者類解耦,解決了目標類和適配者類接口不一致的問題。
    • 缺點
      • 對類適配器來講,更換適配器的實現過程比較複雜。
    • UML結構圖:
    • 模式實現:
      • 類適配器模式
        public interface Target {
            public void request();
        }
        
        public class Adaptee {
            public void specificRequest() {       
                System.out.println("適配者中的業務代碼被調用!");
            }
        }
        
        public class ClassAdapter extends Adaptee implements Target {
        
            public void request() {
                specificRequest();
            }
        }
        
        public class ClassAdapterTest {
            public static void main(String[] args) {
                System.out.println("類適配器模式測試:");
                Target target = new ClassAdapter();
                target.request();
            }
        }
      • 對象適配器模式
        public interface Target {
            public void request();
        }
        
        public class Adaptee {
            public void specificRequest() {       
                System.out.println("適配者中的業務代碼被調用!");
            }
        }
        
        public class ObjectAdapter implements Target {
        
            private Adaptee adaptee;
            
            public ObjectAdapter(Adaptee adaptee) {
                this.adaptee = adaptee;
            }
            
            public void request() {
                adaptee.specificRequest();
            }
        }
        
        public class ObjectAdapterTest {
            public static void main(String[] args) {
                System.out.println("對象適配器模式測試:");
                Adaptee adaptee = new Adaptee();
                Target target = new ObjectAdapter(adaptee);
                target.request();
            }
        }
  • 橋接模式
    • 若是說某個系統可以從多個角度來進行分類,且每一種分類均可能會變化,那麼咱們須要作的就是講這多個角度分離出來,使得他們能獨立變化,減小他們之間的耦合,這個分離過程就使用了橋接模式。
    • 所謂橋接模式就是講抽象部分和實現部分隔離開來,使得他們可以獨立變化。橋接模式將繼承關係轉化成關聯關係,封裝了變化,完成了解耦,減小了系統中類的數量,也減小了代碼量。
    • 優勢
      • 因爲抽象與實現分離,因此擴展能力強;
      • 其實現細節對客戶透明。
    • 缺點
      • 因爲聚合關係創建在抽象層,要求開發者針對抽象化進行設計與編程,這增長了系統的理解與設計難度。
    • 主要角色UML結構圖:
      • 抽象化(Abstraction)角色:定義抽象類,幷包含一個對實現化對象的引用。
      • 擴展抽象化(Refined    Abstraction)角色:是抽象化角色的子類,實現父類中的業務方法,並經過組合關係調用實現化角色中的業務方法。
      • 實現化(Implementor)角色:定義實現化角色的接口,供擴展抽象化角色調用。
      • 具體實現化(Concrete Implementor)角色:給出實現化角色接口的具體實現。
    • 模式實現:
      public interface Implementor { public void OperationImpl(); } public class ConcreteImplementorA implements Implementor { public void OperationImpl() { System.out.println("具體實現化(Concrete Implementor)角色被訪問" ); } } public abstract class Abstraction { protected Implementor imple; protected Abstraction(Implementor imple) { this.imple = imple; } public abstract void Operation(); } public class RefinedAbstraction extends Abstraction{ protected RefinedAbstraction(Implementor imple) { super(imple); } public void Operation() { System.out.println("擴展抽象化(Refined Abstraction)角色被訪問" ); imple.OperationImpl(); } } public class BridgeTest { public static void main(String[] args) { Implementor imple = new ConcreteImplementorA(); Abstraction abs = new RefinedAbstraction(imple); abs.Operation(); } }
  • 組合模式裝飾模式
    • 組合模式組合多個對象造成樹形結構以表示「總體-部分」的結構層次。
    • 它定義瞭如何將容器對象和葉子對象進行遞歸組合,使得客戶在使用的過程當中無須進行區分,能夠對他們進行一致的處理。
    • 在使用組合模式中須要注意一點也是組合模式最關鍵的地方:葉子對象和組合對象實現相同的接口。這就是組合模式可以將葉子節點和對象節點進行一致處理的緣由。
    • 雖然組合模式可以清晰地定義分層次的複雜對象,也使得增長新構件也更容易,可是這樣就致使了系統的設計變得更加抽象,若是系統的業務規則比較複雜的話,使用組合模式就有必定的挑戰了。
    • 優勢
      • 組合模式使得客戶端代碼能夠一致地處理單個對象和組合對象,無須關心本身處理的是單個對象,仍是組合對象,這簡化了客戶端代碼;
      • 更容易在組合體內加入新的對象,客戶端不會由於加入了新的對象而更改源代碼,知足「開閉原則」;
    • 缺點
      • 設計較複雜,客戶端須要花更多時間理清類之間的層次關係;
      • 不容易限制容器中的構件;
      • 不容易用繼承的方法來增長構件的新功能;
    • 主要角色
      • 抽象構件(Component)角色:它的主要做用是爲樹葉構件和樹枝構件聲明公共接口,並實現它們的默認行爲。在透明式的組合模式中抽象構件還聲明訪問和管理子類的接口;在安全式的組合模式中不聲明訪問和管理子類的接口,管理工做由樹枝構件完成。
      • 樹葉構件(Leaf)角色:是組合中的葉節點對象,它沒有子節點,用於實現抽象構件角色中 聲明的公共接口。
      • 樹枝構件(Composite)角色:是組合中的分支節點對象,它有子節點。它實現了抽象構件角色中聲明的接口,它的主要做用是存儲和管理子部件,一般包含 Add()、Remove()、GetChild() 等方法。
    • UML結構圖:
    • 模式實現
      public interface Component {
          public void add(Component c);
          public void remove(Component c);
          public Component getChild(int i);
          public void operation();
      }
      
      public class Leaf implements Component {
          
          private String name;
          
          public Leaf(String name) {
              this.name = name;
          }
      
          public void add(Component c) {
              
          }
      
          public void remove(Component c) {
          }
      
          public Component getChild(int i) {
              return null;
          }
      
          public void operation() {
              System.out.println("樹葉" + name + ":被訪問!"); 
          }
      }
      
      public class Composite implements Component {
          
          private ArrayList<Component> children = new ArrayList<Component>();
      
          public void add(Component c) {
              children.add(c);
          }
      
          public void remove(Component c) {
              children.remove(c);
          }
      
          public Component getChild(int i) {
              return children.get(i);
          }
      
          public void operation() {
              for(Object obj : children) {
                  ((Component)obj).operation();
              }
          }
      }
      
      public class CompositePattern {
          public static void main(String[] args) {
              Component c0 = new Composite();
              Component c1 = new Composite();
              Component leaf1 = new Leaf("1");
              Component leaf2 = new Leaf("2");
              Component leaf3 = new Leaf("3");
              c0.add(leaf1);
              c0.add(c1);
              c1.add(leaf2);
              c1.add(leaf3);
              c0.operation();
          }
      }
  • 裝飾模式
    • 咱們能夠經過繼承和組合的方式來給一個對象添加行爲,雖然使用繼承可以很好擁有父類的行爲,可是它存在幾個缺陷:1、對象之間的關係複雜的話,系統變得複雜不利於維護。2、容易產生「類爆炸」現象。3、是靜態的。在這裏咱們能夠經過使用裝飾者模式來解決這個問題。
    • 裝飾者模式,動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更加有彈性的替代方案。雖然裝飾者模式可以動態將責任附加到對象上,可是他會產生許多的細小對象,增長了系統的複雜度。
    • 優勢
      • 採用裝飾模式擴展對象的功能比採用繼承方式更加靈活。
      • 能夠設計出多個不一樣的具體裝飾類,創造出多個不一樣行爲的組合。
    • 缺點
      • 裝飾模式增長了許多子類,若是過分使用會使程序變得很複雜。
    • 主要角色
      • 抽象構件(Component)角色:定義一個抽象接口以規範準備接收附加責任的對象。
      • 具體構件(Concrete    Component)角色:實現抽象構件,經過裝飾角色爲其添加一些職責。
      • 抽象裝飾(Decorator)角色:實現抽象構件,幷包含具體構件的實例,能夠經過其子類擴展具體構件的功能。
      • 體裝飾(ConcreteDecorator)角色:繼承抽象裝飾的相關方法,並給具體構件對象添加附加的責任。
    • UML結構圖:
    • 模式實現
      public interface Component {
          public void operation();
      }
      
      public class ConcreteComponent implements Component{
          
          public ConcreteComponent() {
              System.out.println("建立具體構件角色");
          }
      
          public void operation() {
              System.out.println("調用具體構件角色的方法operation()");
          }
      }
      
      public class Decorator implements Component {
      
          private Component component;   
          
          public Decorator(Component component) {
              this.component = component;
          }   
          
          public void operation() {
              component.operation();
          }
      }
      
      public class ConcreteDecorator extends Decorator {
          
          public ConcreteDecorator(Component component) {
              super(component);
          }
          
          public void operation() {
              super.operation();
              addedFunction();
          }
          
          public void addedFunction() {
              System.out.println("爲具體構件角色增長額外的功能addedFunction()");           
          }
      }
      
      public class DecoratorPattern {
          public static void main(String[] args) {
              Component p = new ConcreteComponent();
              p.operation();
              System.out.println("---------------------------------");
              Component d = new ConcreteDecorator(p);
              d.operation();
          }
      }
  • 代理模式
  • 亨元模式
  • 外觀模式
相關文章
相關標籤/搜索