8種設計模式:

主要介紹

單例設計模式摧莽,代理設計模式,觀察者設計模式呵俏,模板模式(Template)堆缘, 適配器模式,裝飾模式(Decorator)普碎,命令模式(Command)吼肥,策略模式(Strategy);(單代命 觀模裝適)。

1. 單例模式:

一般包括:懶漢式單例麻车、餓漢式單例缀皱、登記式單例。

  • 特點:
      1动猬、單例類只能有一個實例啤斗。
      2、單例類必須自己創(chuàng)建自己的唯一實例赁咙。

  • 用途:
    在計算機系統(tǒng)中钮莲,線程池、緩存彼水、日志對象崔拥、對話框、打印機凤覆、顯卡的驅動程序對象常被設計成單例链瓦。

  • 示例:

//懶漢式單例類.在第一次調用的時候實例化自己   
public class Singleton {  
  private Singleton() {}  
  private static Singleton single=null;  
  //靜態(tài)工廠方法   
  public static Singleton getInstance() {  
       synchronized (Singleton.class) {    
             if (singleton == null) {    
                singleton = new Singleton();   
             }             
      }    
      return singleton;   
  }  
}

//靜態(tài)內部類時,不需要用同步
public class Singleton {    
  private static class LazyHolder {    
     private static final Singleton INSTANCE = new Singleton();    
  }    
  private Singleton (){}    
  public static final Singleton getInstance() {    
     return LazyHolder.INSTANCE;    
  }    
}   

//餓漢式單例類.在類初始化時盯桦,已經(jīng)自行實例化   
public class Singleton1 {  
  private Singleton1() {}  
  private static final Singleton1 single = new Singleton1(); 
  //靜態(tài)工廠方法   
  public static Singleton1 getInstance() {  
      return single;  
  }  
}

//登記式單例
  /*實際上維護了一組單例類的實例慈俯,將這些實例存放在一個Map(登記薄)中拥峦,對于已經(jīng)登記過的實例贴膘,則從Map直接返回,對于沒有登記的略号,則先登記步鉴,然后返回揪胃。它用的比較少且麻煩,另外其實內部實現(xiàn)還是用的餓漢式單例氛琢,這里忽略喊递。*/

2. 代理模式

是指客戶端并不直接調用實際的對象,而是通過調用代理阳似,來間接的調用實際的對象骚勘。

3. 命令模式

是指為了實現(xiàn)調用者角色與接收者角色之間,沒有任何依賴關系撮奏,即完全解耦俏讹。

  • 命令模式的4個角色:
    Command:定義命令的統(tǒng)一接口
    ConcreteCommand:Command接口的實現(xiàn)者,用來執(zhí)行具體的命令畜吊,有時也直接用來充當Receiver泽疆。
    Receiver:命令的實際執(zhí)行者
    Invoker:命令的請求者,是命令模式中最重要的角色玲献。這個角色用來對各個命令進行控制殉疼。

  • 示例:

//通用Receiver類
public abstract class Receiver {
    public abstract void doSomething();
}

//具體Receiver類
public class ConcreteReciver1 extends Receiver{ 
    //每個接收者都必須處理一定的業(yè)務邏輯 
    public void doSomething(){ } 
} 
public class ConcreteReciver2 extends Receiver{ 
    //每個接收者都必須處理一定的業(yè)務邏輯 
    public void doSomething(){ } 
}

//抽象Command類
public abstract class Command {
    public abstract void execute();
}

//具體的Command類
public class ConcreteCommand1 extends Command { 
    //對哪個Receiver類進行命令處理 
    private Receiver receiver; 
    //構造函數(shù)傳遞接收者 
    public ConcreteCommand1(Receiver _receiver){
        this.receiver = _receiver; 
    } 

    //必須實現(xiàn)一個命令 
    public void execute() { 
    //業(yè)務處理 
        this.receiver.doSomething(); 
    } 
} 

public class ConcreteCommand2 extends Command { 
    //哪個Receiver類進行命令處理 
    private Receiver receiver; 
    //構造函數(shù)傳遞接收者 
    public ConcreteCommand2(Receiver _receiver){
        this.receiver = _receiver; 
    } 
    //必須實現(xiàn)一個命令 
    public void execute() { 
        //業(yè)務處理 
        this.receiver.doSomething();
    } 
}

//調用者Invoker類
public class Invoker {
    private Command command;
    
    public void setCommand(Command _command){
        this.command = _command;
    }
    
    public void action() {
        this.command.execute();
    }
}

//場景類
public class Client {
    public static void main(String[] args){
        Invoker invoker = new Invoker();
        Receiver receiver = new ConcreteReceiver1();
        
        Command command = new ConcreteCommand1(receiver);
        invoker.setCommand(command);
        invoker.action();
    }
}
4. 觀察者設計模式

是指在對象之間定義了一對多的依賴,這樣一來捌年,當一個對象改變狀態(tài)瓢娜,依賴它的對象會收到通知并自動更新。

  • 其包含四個角色:

    1. 抽象被觀察者角色:也就是一個抽象主題礼预,它把所有對觀察者對象的引用保存在一個集合中眠砾,每個主題都可以有任意數(shù)量的觀察者。抽象主題提供一個接口托酸,可以增加和刪除觀察者角色褒颈。一般用一個抽象類和接口來實現(xiàn)。
    2. 抽象觀察者角色:為所有的具體觀察者定義一個接口励堡,在得到主題通知時更新自己哈肖。
    3. 具體被觀察者角色:也就是一個具體的主題,在集體主題的內部狀態(tài)改變時念秧,所有登記過的觀察者發(fā)出通知。
    4. 具體觀察者角色:實現(xiàn)抽象觀察者角色所需要的更新接口布疼,一邊使本身的狀態(tài)與制圖的狀態(tài)相協(xié)調
  • 使用場景舉例:
      有一個微信公眾號服務摊趾,不定時發(fā)布一些消息,關注公眾號就可以收到推送消息游两,取消關注就收不到推送消息砾层。

  • 示例:

/***
 * 抽象被觀察者接口
 * 聲明了添加、刪除贱案、通知觀察者方法
 * @author jstao
 *
 */
public interface Observerable {
    
    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObserver();
    
}

//定義一個抽象觀察者接口
/***
 * 抽象觀察者
 * 定義了一個update()方法肛炮,當被觀察者調用notifyObservers()方法時,觀察者的update()方法會被回調。
 * @author jstao
 *
 */
public interface Observer {
    public void update(String message);
}

//定義被觀察者侨糟,實現(xiàn)了Observerable接口碍扔,對Observerable接口的三個方法進行了具體實現(xiàn),同時有一個List集合秕重,用以保存注冊的觀察者不同,等需要通知觀察者時,遍歷該集合即可溶耘。

/**
 * 被觀察者二拐,也就是微信公眾號服務
 * 實現(xiàn)了Observerable接口,對Observerable接口的三個方法進行了具體實現(xiàn)
 * @author jstao
 *
 */
public class WechatServer implements Observerable {
   
    //注意到這個List集合的泛型參數(shù)為Observer接口凳兵,設計原則:面向接口編程而不是面向實現(xiàn)編程
    private List<Observer> list;
    private String message;
    
    public WechatServer() {
        list = new ArrayList<Observer>();
    }
    
    @Override
    public void registerObserver(Observer o) {
        
        list.add(o);
    }
    
    @Override
    public void removeObserver(Observer o) {
        if(!list.isEmpty())
            list.remove(o);
    }

    //遍歷
    @Override
    public void notifyObserver() {
        for(int i = 0; i < list.size(); i++) {
            Observer oserver = list.get(i);
            oserver.update(message);
        }
    }
    
    public void setInfomation(String s) {
        this.message = s;
        System.out.println("微信服務更新消息: " + s);
        //消息更新百新,通知所有觀察者
        notifyObserver();
    }

}

//定義具體觀察者,微信公眾號的具體觀察者為用戶User
/**
 * 觀察者
 * 實現(xiàn)了update方法
 * @author jstao
 *
 */
public class User implements Observer {
    private String name;
    private String message;
    
    public User(String name) {
        this.name = name;
    }
    
    @Override
    public void update(String message) {
        this.message = message;
        read();
    }
    
    public void read() {
        System.out.println(name + " 收到推送消息: " + message);
    }
}

5. 模板模式

定義一個操作中算法的骨架庐扫,而將一些步驟延遲到子類中饭望。也就是說,要在父類中定義一個完成該事情的總方法聚蝶,按照完成事件需要的步驟去調用其每個步驟的實現(xiàn)方法杰妓。每個步驟的具體實現(xiàn),由子類完成碘勉。

  • 示例:
public abstract class DodishTemplate {  //模板類
    /**
     * 具體的整個過程
     */
    protected void dodish(){
        this.preparation();
        this.doing();
        this.carriedDishes();
    }
    /**
     * 備料
     */
    public abstract void preparation();
    /**
     * 做菜
     */
    public abstract void doing();
    /**
     * 上菜
     */
    public abstract void carriedDishes ();
}


public class EggsWithTomato extends DodishTemplate{ //具體實現(xiàn)類

    @Override
    public void preparation() {
        System.out.println("洗并切西紅柿巷挥,打雞蛋。");
    }

    @Override
    public void doing() {
        System.out.println("雞蛋倒入鍋里验靡,然后倒入西紅柿一起炒倍宾。");
    }

    @Override
    public void carriedDishes() {
        System.out.println("將炒好的西紅寺雞蛋裝入碟子里,端給客人吃胜嗓。");
    }

}


//代碼中調用:
 DodishTemplate eggsWithTomato = new EggsWithTomato();
 eggsWithTomato.dodish();
6. 裝飾模式

也叫做包裝模式高职,是結構型設計模式之一。目的是為了給一個類或對象增加行為辞州≌浚可以是繼承的一種替代。

  • 四個角色:
    Component:抽象組件变过,可以是一個接口或抽象類埃元,是被裝飾的原始對象
    ConcreteComponent:組件的具體實現(xiàn)類。是被裝飾的具體對象媚狰。
    Decorator:抽象的裝飾者岛杀。職責是裝飾被裝飾的對象。內部一定有一個對被裝飾者的引用崭孤。一般情況下也是一個抽象類类嗤,根據(jù)具體邏輯實現(xiàn)不同的子類糊肠。如果邏輯簡單可以直接是實現(xiàn)類。
    ConcreteDecoratorA遗锣,B:具體的裝飾者货裹。

  • 示例:

//先抽象組件類:
public abstract class Component {
    public abstract void operate();
}
組件的一個具體實現(xiàn)類,也就是被裝飾者者:

public class ConcreteComponent extends Component {
    @Override
    public void operate() {
        System.out.println("被裝飾者的操作");
    }
}

//抽象的裝飾者黄伊,持有一個被裝飾者的引用:
public abstract class Decorator extends Component { 
    private Component component;

    public Decorator(Component component) { //采用傳參方式泪酱,替代繼承類的方式,這樣區(qū)分開繼承利于后期管理
        this.component = component;
    }

    @Override
    public void operate() {
        component.operate();
    }
}


//具體的兩個裝飾者还最,拓展功能:
public class ConcreteDecoratorA extends Decorator {
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void operate() {
        operateA();
        super.operate();
        operateB();
    }

    private void operateA(){
        System.out.println("裝飾者A在被裝飾者的操作之前加些操作");
    }
    private void operateB(){
        System.out.println("裝飾者A在被裝飾者的操作之前后加些操作");
    }
}
public class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }
    @Override
    public void operate() {
        operateA();
        super.operate();
        operateB();
    }

    private void operateA(){
        System.out.println("裝飾者B在被裝飾者的操作之前加些操作");
    }
    private void operateB(){
        System.out.println("裝飾者B在被裝飾者的操作之前后加些操作");
    }
}


//客戶端調用:
public class Client {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA(component);
        ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB(component);

        concreteDecoratorA.operate();
        concreteDecoratorB.operate();
    }
}
7. 適配器模式

將一個類的接口轉換成客戶希望的另外一個接口墓阀。適配器模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作,可以理解成轉換器拓轻。 例子:https://blog.csdn.net/lmb55/article/details/51008762

8. 策略模式

定義了一系列的算法斯撮,并將每一個算法封裝起來,而且使他們可以相互替換扶叉,讓算法"獨立"于使用它的客戶而獨立變化勿锅。

  • 使用場景:
    1.針對同一類型問題的多種處理方式,僅僅是具體行為有差別時枣氧;
    2.需要安全地封裝多種同一類型的操作時溢十;
    3.出現(xiàn)同一抽象類有多個子類,而又需要使用 if-else 或者 switch-case 來選擇具體子類時达吞。

  • 示例:

public interface CalPrice {
    //根據(jù)原價返回一個最終的價格
    Double calPrice(Double orgnicPrice);
}

public class Orgnic implements CalPrice {

    @Override
    public Double calPrice(Double orgnicPrice) {
        return orgnicPrice;
    }
}

public class Vip implements CalPrice {
    @Override
    public Double calPrice(Double orgnicPrice) {
        return orgnicPrice * 0.9;
    }
}

public class SuperVip implements CalPrice {
    @Override
    public Double calPrice(Double orgnicPrice) {
        return orgnicPrice * 0.8;
    }
}

public class GoldVip implements CalPrice {
    @Override
    public Double calPrice(Double orgnicPrice) {
        return orgnicPrice * 0.7;
    }
}

public class Player {
    private Double totalAmount = 0D;//客戶在鵝廠消費的總額
    private Double amount = 0D;//客戶單次消費金額
    private CalPrice calPrice = new Orgnic();//每個客戶都有一個計算價格的策略张弛,初始都是普通計算,即原價

    //客戶購買皮膚酪劫,就會增加它的總額
    public void buy(Double amount) {
        this.amount = amount;
        totalAmount += amount;
        if (totalAmount > 30000) {//30000則改為金牌會員計算方式
            calPrice = new GoldVip();
        } else if (totalAmount > 20000) {//類似
            calPrice = new SuperVip();
        } else if (totalAmount > 10000) {//類似
            calPrice = new Vip();
        }
    }

    //計算客戶最終要付的錢
    public Double calLastAmount() {
        return calPrice.calPrice(amount);
    }
}

//調用
Player player = new Player();
player.buy(5000D);
System.out.println("玩家需要付錢:" + player.calLastAmount());

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末吞鸭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子覆糟,更是在濱河造成了極大的恐慌刻剥,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滩字,死亡現(xiàn)場離奇詭異造虏,居然都是意外死亡,警方通過查閱死者的電腦和手機麦箍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門漓藕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人内列,你說我怎么就攤上這事”陈剩” “怎么了话瞧?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵嫩与,是天一觀的道長。 經(jīng)常有香客問我交排,道長划滋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任埃篓,我火速辦了婚禮处坪,結果婚禮上,老公的妹妹穿的比我還像新娘架专。我一直安慰自己同窘,他們只是感情好,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布部脚。 她就那樣靜靜地躺著想邦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪委刘。 梳的紋絲不亂的頭發(fā)上丧没,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機與錄音锡移,去河邊找鬼呕童。 笑死,一個胖子當著我的面吹牛淆珊,可吹牛的內容都是我干的夺饲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼套蒂,長吁一口氣:“原來是場噩夢啊……” “哼钞支!你這毒婦竟也來了?” 一聲冷哼從身側響起操刀,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤烁挟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后骨坑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撼嗓,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年欢唾,在試婚紗的時候發(fā)現(xiàn)自己被綠了且警。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡礁遣,死狀恐怖斑芜,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情祟霍,我是刑警寧澤杏头,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布杈笔,位于F島的核電站办龄,受9級特大地震影響优训,放射性物質發(fā)生泄漏搁吓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一寓娩、第九天 我趴在偏房一處隱蔽的房頂上張望叛氨。 院中可真熱鬧,春花似錦棘伴、人聲如沸寞埠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽畸裳。三九已至,卻和暖如春淳地,著一層夾襖步出監(jiān)牢的瞬間怖糊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工颇象, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留伍伤,地道東北人。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓遣钳,卻偏偏與公主長得像扰魂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蕴茴,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內容

  • 設計模式匯總 一劝评、基礎知識 1. 設計模式概述 定義:設計模式(Design Pattern)是一套被反復使用、多...
    MinoyJet閱讀 3,948評論 1 15
  • 真誠的倦淀,TNANKS蒋畜。 個人Github-23種設計模式案例鏈接 創(chuàng)建型模式 工廠模式 工廠模式(Factory ...
    水清_木秀閱讀 26,076評論 11 204
  • 對, 這個話題其實牽扯不到Shopify, 大家會想我想賣什么就賣什么唄,干嘛弄的這么麻煩撞叽。 先說風險吧姻成,品不好選...
    Shopify怎么運營閱讀 5,993評論 0 8
  • 在一家不大不少的超市工作,個人認為是比較有收獲的愿棋。大店鋪分工明確科展,工作內容單一易乏味;小店鋪銷售的品類太單一糠雨,不好...
    容書仁閱讀 479評論 2 2
  • 蝴蝶蘭夢閱讀 200評論 0 0