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

分類

創(chuàng)建型

創(chuàng)建對(duì)象時(shí),不再直接實(shí)例化對(duì)象;而是根據(jù)特定場(chǎng)景,由程序來(lái)確定創(chuàng)建對(duì)象的方式,從而保證更高的性能、更好的架構(gòu)優(yōu)勢(shì)。創(chuàng)建型模式主要有簡(jiǎn)單工廠模式(并不是23種設(shè)計(jì)模式之一)、工廠方法、抽象工廠模式、單例模式、生成器模式和原型模式。

結(jié)構(gòu)型

用于幫助將對(duì)個(gè)對(duì)象組織成更大的結(jié)構(gòu)。結(jié)構(gòu)型模式主要有適配器模式、橋接模式、組合器模式、裝飾器模式、門面模式、享元模式和代理模式。

行為型

用于幫助系統(tǒng)間各對(duì)象的通信,以及如何控制復(fù)雜系統(tǒng)中的流程。行為模式主要有命令模式、解釋器模式、迭代器模式、中介者模式、備忘錄模式、觀察者模式、狀態(tài)模式、策略模式、模板模式和訪問(wèn)者模式。

單例模式

如果一個(gè)類始終只能創(chuàng)建一個(gè)實(shí)例,則這個(gè)類被稱為單例類,這種模式就被稱為單例模式。
Spring推薦將所有業(yè)務(wù)邏輯組件、DAO組件、數(shù)據(jù)源組件等配置成單例的行為方式,因?yàn)檫@些組件無(wú)需保存任何用戶狀態(tài)。
為了保證一個(gè)類只能產(chǎn)生一個(gè)實(shí)例,程序不能允許自由創(chuàng)建該類的對(duì)象,只需要使用private修飾該類的構(gòu)造器,從而將該類的構(gòu)造器隱藏起來(lái)。同時(shí)提供一個(gè)public方法作為該類的訪問(wèn)點(diǎn),用于創(chuàng)建該類的對(duì)象,且該方法必須使用static修飾(因?yàn)檎{(diào)用該方法之前還不存在對(duì)象,因此調(diào)用該方法的不可能是對(duì)象,只能是類)。除此之外,該類還必須緩存已經(jīng)創(chuàng)建的對(duì)象,否則該類無(wú)法知道是否曾經(jīng)創(chuàng)建過(guò)實(shí)例,也就無(wú)法保證只創(chuàng)建一個(gè)實(shí)例。為此該類需要使用一個(gè)靜態(tài)屬性來(lái)保存曾經(jīng)創(chuàng)建的實(shí)例,且該屬性需要被靜態(tài)方法訪問(wèn),所以該屬性也應(yīng)使用static修飾。

class Singleton {
   //使用一個(gè)類變量緩存曾經(jīng)創(chuàng)建的實(shí)例
   private static Singleton instance;
   // 將構(gòu)造器使用private修飾,隱藏該構(gòu)造器
   private Singleton(){}
   //提供一個(gè)靜態(tài)方法,用于返回Singleton實(shí)例
   //該方法可以加入自定義的控制,保證只產(chǎn)生一個(gè)Singleton對(duì)象
   public static Singleton getInstance(){
       //如果instance為null,表明不曾創(chuàng)建Singleton對(duì)象
       //如果instance不為null,則表明已創(chuàng)建了Singleton對(duì)象,將不會(huì)執(zhí)行該方法
       if(instance == null){
           instance = new Singleton();
       }
       return instance;
   }
}

工廠

  • 簡(jiǎn)單工廠
  • 工廠方法
  • 沖向工廠
    定義一個(gè)Factory專門用于生產(chǎn)類對(duì)象。使用方通過(guò)Factory調(diào)用對(duì)應(yīng)的類對(duì)象,將使用者和類對(duì)象解耦,由統(tǒng)一工廠耦合。如果需要更改類對(duì)象,不需要更改工廠的調(diào)用者。
    如果工廠直接生產(chǎn)被調(diào)用對(duì)象,那就是簡(jiǎn)單工廠模式;如果工廠生產(chǎn)了工廠對(duì)象,那就是會(huì)升級(jí)成抽象工廠模式。

代理模式

InvokationHandler實(shí)現(xiàn)

public class MyInvokationHandler implements InvocationHandler {
   //需要被代理的對(duì)象
   private Object target;

   public void setTarget(Object target) {
       this.target = target;
   }

   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       TxUtil tx = new TxUtil();
       tx.beginTx();

       Object result = method.invoke(target,args);
       tx.endTx();
       return result;
   }
}
public class MyProxyFactory {

   //為指定target生成動(dòng)態(tài)代理對(duì)象
   public static Object getProxy(Object target) throws Exception{
       //創(chuàng)建一個(gè)MyInvokationHandler對(duì)象
       MyInvokationHandler handler = new MyInvokationHandler();

       //為MyInvokationHandler設(shè)置target對(duì)象
       handler.setTarget(target);
       //創(chuàng)建并返回一個(gè)動(dòng)態(tài)代理
       return Proxy.newProxyInstance(target.getClass().getClassLoader() , >target.getClass().getInterfaces(),handler);
   }
}

命令模式

思考一種場(chǎng)景,某個(gè)方法需要完成某一個(gè)功能,完成這個(gè)功能的參數(shù)要求可以變化,具體執(zhí)行的代碼也可以變化,即需要把“處理行為”也作為一個(gè)參數(shù)傳入方法。

public interface Command {
   void process(int[] target);
}
public class ProcessArray {
   public void each(int[] target,Command cmd){
       cmd.process(target);
   }
}
  public class CommandTest {
    public static void main(String[] args) {
       ProcessArray pa = new ProcessArray();
       int[] target = {3,-4,6,4};
       pa.each(target, new Command() {
           @Override
           public void process(int[] target) {
               for(int tmp : target){
                   System.out.println("迭代輸出目標(biāo)數(shù)組的元素:"+ tmp);
               }
           }
       });
   }
}

策略模式

思考一種場(chǎng)景,某書店需要提供打折場(chǎng)景(vip折扣,舊書兌換折扣。。。)
其用意是針對(duì)一組算法,將每一個(gè)算法封裝到具有共同接口的獨(dú)立的類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響到客戶端的情況下發(fā)生變化。策略模式是對(duì)算法的包裝,是把使用算法的責(zé)任和算法本身分割開來(lái),委派給不同的對(duì)象管理。策略模式通常把一個(gè)系列的算法包裝到一系列的策略類里面,作為一個(gè)抽象策略類的子類。用一句話來(lái)說(shuō),就是:“準(zhǔn)備一組算法,并將每一個(gè)算法封裝起來(lái),使得它們可以互換”。

橋接模式

假如有一個(gè)飯店提供菜單:牛肉面、豬肉面...選擇添加辣椒時(shí):無(wú)辣、微辣、中辣...
此時(shí)可以選擇橋接模式(把變化的部分抽象出來(lái))然后使得變化部分與主類分離開來(lái);通過(guò)組合滿足業(yè)務(wù)的需要。

觀察者模式

觀察者模式定義了對(duì)象間的一對(duì)多依賴關(guān)系,讓一個(gè)或者多個(gè)觀察者對(duì)象觀察一個(gè)主題對(duì)象。當(dāng)主題對(duì)象的狀態(tài)發(fā)生變化時(shí),系統(tǒng)能通知所有的依賴于次對(duì)象的觀察者對(duì)象,從而使得觀察者對(duì)象能夠自動(dòng)更新。

觀察者模式主要的4個(gè)角色:

  • 被觀察者的抽象基類。一般有java.util.Observable提供。
  • 觀察者接口 一般由java.util.Observer提供
  • 被觀察者實(shí)現(xiàn)類 Product
  • 觀察者實(shí)現(xiàn)類
//被觀察者
public class Product extends Observable {

    //定義兩個(gè)成員變量
    private String name;
    private double price;

    public Product(){}

    public Product(String name,double price){
        this.name = name;
        this.price = price;
    }

    public String getName(){
        return name;
    }

    //當(dāng)程序調(diào)用name的setter方法來(lái)修改Product的name成員變量時(shí),程序自然觸發(fā)該對(duì)象上注冊(cè)的所有觀察者
    public void setName(String name){
        this.name = name;
        this.setChanged();
        notifyObservers(name);
    }

    public double getPrice(){
        return price;
    }

    public void setPrice(double price){
        this.price = price;
        this.setChanged();
        notifyObservers(price);
    }
}

//觀察者實(shí)現(xiàn)
public class NameObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        if( arg instanceof String ){
            String name = (String) arg;
            JFrame f = new JFrame("觀察者");
            JLabel l = new JLabel("名稱改變?yōu)椋? + name);
            f.add(l);
            f.pack();
            f.setVisible(true);
            System.out.println("名稱觀察者:" + o + "物品名稱已經(jīng)改變?yōu)椋? + name);
        }
    }
}
//注冊(cè)觀察者至被觀察者
public class Main {
    public static void main(String[] args) {
        Product p = new Product("電視劇",176);

        NameObserver no = new NameObserver();
        PriceObserver po = new PriceObserver();

//        p.registObserver(no);
//        p.registObserver(po);
        p.addObserver(no);
        p.addObserver(po);

        p.setName("書桌");
        p.setPrice(345f);

    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容