【常用設(shè)計(jì)模式】觀察者-模板-策略-責(zé)任鏈-適配器-代理-裝飾器-工廠 等13個(gè)最常用設(shè)計(jì)模式

==目錄==

==前言==

1. 設(shè)計(jì)模式分類

創(chuàng)建型模式:用來(lái)構(gòu)建對(duì)象以便能從實(shí)現(xiàn)系統(tǒng)解耦
結(jié)構(gòu)型模式:用不同的對(duì)象組成大規(guī)模的對(duì)象結(jié)構(gòu)
行為型模式:用來(lái)在對(duì)象中管理算法、關(guān)系、責(zé)任

對(duì)象層面:處理對(duì)象之間的關(guān)系张吉,決定于運(yùn)行期
類層面:處理類的關(guān)系,決定于在編譯器

2. 設(shè)計(jì)模式六大原則

1-開(kāi)閉原則:
    對(duì)擴(kuò)展開(kāi)放烹植,對(duì)修改關(guān)閉。
    就是代碼需要擴(kuò)展的時(shí)候愕贡,不需要修改原有的代碼草雕。
    而實(shí)現(xiàn)開(kāi)閉原則的關(guān)鍵步驟就是抽象化。
    
2-里氏代換原則:
    是對(duì)開(kāi)閉原則的補(bǔ)充固以。
    對(duì)實(shí)現(xiàn)抽象化的具體步驟的規(guī)范墩虹。
    
3-依賴倒轉(zhuǎn)原則:
    是開(kāi)閉原則的基礎(chǔ)。
    針對(duì)接口編程憨琳,依賴抽象而不是具體诫钓。
    
4-接口隔離原則:
    使用多個(gè)隔離的接口,比使用單個(gè)接口要好篙螟。
    降低類之間的耦合度菌湃。
    
5-最小知識(shí)原則:
    一個(gè)實(shí)體應(yīng)當(dāng)盡量少地與其他實(shí)體之間發(fā)生相互作用,使得系統(tǒng)功能模塊相對(duì)獨(dú)立
    
6-合成/聚合復(fù)用原則:
    盡量使用合成/聚合的方式遍略,而不是使用繼承
    
面向?qū)ο笤瓌t:
    對(duì)接口編程而不是對(duì)實(shí)現(xiàn)編程惧所。
    優(yōu)先使用對(duì)象組合而不是繼承场梆。

==1-行為型==

==1-觀察者模式-行為型==

image
優(yōu)點(diǎn): 
1、觀察者和被觀察者是抽象耦合的纯路。 
2、建立一套觸發(fā)機(jī)制寞忿。

缺點(diǎn): 
1驰唬、如果一個(gè)被觀察者對(duì)象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間腔彰。 
2叫编、如果在觀察者和觀察目標(biāo)之間有循環(huán)依賴的話,觀察目標(biāo)會(huì)觸發(fā)它們之間進(jìn)行循環(huán)調(diào)用霹抛,可能導(dǎo)致系統(tǒng)崩潰搓逾。 
3、觀察者模式?jīng)]有相應(yīng)的機(jī)制讓觀察者知道所觀察的目標(biāo)對(duì)象是怎么發(fā)生變化的杯拐,而僅僅只是知道觀察目標(biāo)發(fā)生了變化霞篡。

使用場(chǎng)景:
1、一個(gè)抽象模型有兩個(gè)方面端逼,其中一個(gè)方面依賴于另一個(gè)方面朗兵。將這些方面封裝在獨(dú)立的對(duì)象中使它們可以各自獨(dú)立地改變和復(fù)用。
2顶滩、一個(gè)對(duì)象的改變將導(dǎo)致其他一個(gè)或多個(gè)對(duì)象也發(fā)生改變余掖,而不知道具體有多少對(duì)象將發(fā)生改變,可以降低對(duì)象之間的耦合度礁鲁。
3盐欺、一個(gè)對(duì)象必須通知其他對(duì)象,而并不知道這些對(duì)象是誰(shuí)仅醇。
4冗美、需要在系統(tǒng)中創(chuàng)建一個(gè)觸發(fā)鏈,A對(duì)象的行為將影響B(tài)對(duì)象着憨,B對(duì)象的行為將影響C對(duì)象……墩衙,可以使用觀察者模式創(chuàng)建一種鏈?zhǔn)接|發(fā)機(jī)制。
1. 創(chuàng)建主題
public class Subject {
   
   private List<Observer> observers = new ArrayList<Observer>();
   private int state;
 
   public int getState() {
      return state;
   }
 
   public void setState(int state) {
      this.state = state;
      notifyAllObservers();
   }
 
   public void attach(Observer observer){
      observers.add(observer);      
   }
 
   public void notifyAllObservers(){
      for (Observer observer : observers) {
         observer.update();
      }
   }  
}
2. 創(chuàng)建觀察者抽象類
public abstract class Observer {
   protected Subject subject;
   public abstract void update();
}
3. 創(chuàng)建實(shí)體觀察者類
public class BinaryObserver extends Observer{
 
   public BinaryObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
      System.out.println( "Binary String: " 
      + Integer.toBinaryString( subject.getState() ) ); 
   }
}

public class OctalObserver extends Observer{
 
   public OctalObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
     System.out.println( "Octal String: " 
     + Integer.toOctalString( subject.getState() ) ); 
   }
}

public class HexaObserver extends Observer{
 
   public HexaObserver(Subject subject){
      this.subject = subject;
      this.subject.attach(this);
   }
 
   @Override
   public void update() {
      System.out.println( "Hex String: " 
      + Integer.toHexString( subject.getState() ).toUpperCase() ); 
   }
}
4. 應(yīng)用
public class ObserverPatternDemo {
   public static void main(String[] args) {
      Subject subject = new Subject();
 
      new HexaObserver(subject);
      new OctalObserver(subject);
      new BinaryObserver(subject);
 
      System.out.println("First state change: 15");   
      subject.setState(15);
      System.out.println("Second state change: 10");  
      subject.setState(10);
   }
}
5. 執(zhí)行程序甲抖,輸出結(jié)果:
First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010

==2-模板模式-行為型==

模板
優(yōu)點(diǎn): 
1漆改、封裝不變部分,擴(kuò)展可變部分准谚。 
2挫剑、提取公共代碼,便于維護(hù)柱衔。 
3樊破、行為由父類控制愉棱,子類實(shí)現(xiàn)。

缺點(diǎn):
每一個(gè)不同的實(shí)現(xiàn)都需要一個(gè)子類來(lái)實(shí)現(xiàn)哲戚,導(dǎo)致類的個(gè)數(shù)增加奔滑,使得系統(tǒng)更加龐大。

使用場(chǎng)景: 
1顺少、有多個(gè)子類共有的方法朋其,且邏輯相同。 
2脆炎、重要的梅猿、復(fù)雜的方法,可以考慮作為模板方法秒裕。
1. 創(chuàng)建模板抽象類
public abstract class Game {
   abstract void initialize();
   abstract void startPlay();
   abstract void endPlay();
   //模板
   public final void play(){
      //初始化游戲
      initialize();
      //開(kāi)始游戲
      startPlay();
      //結(jié)束游戲
      endPlay();
   }
}
2. 繼承模板抽象類
public class Cricket extends Game {
   @Override
   void endPlay() {
      System.out.println("Cricket Game Finished!");
   }
   @Override
   void initialize() {
      System.out.println("Cricket Game Initialized! Start playing.");
   }
   @Override
   void startPlay() {
      System.out.println("Cricket Game Started. Enjoy the game!");
   }
}

public class Football extends Game {
   @Override
   void endPlay() {
      System.out.println("Football Game Finished!");
   }
   @Override
   void initialize() {
      System.out.println("Football Game Initialized! Start playing.");
   }
   @Override
   void startPlay() {
      System.out.println("Football Game Started. Enjoy the game!");
   }
}
3. 應(yīng)用
public class TemplatePatternDemo {
   public static void main(String[] args) {
 
      Game game = new Cricket();
      game.play();
      System.out.println();
      game = new Football();
      game.play();      
   }
}
4. 執(zhí)行程序袱蚓,輸出結(jié)果:
Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!

Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!

==3-策略模式-行為型==

策略
優(yōu)點(diǎn): 
1、算法可以自由切換几蜻。 
2喇潘、避免使用多重條件判斷。 
3梭稚、擴(kuò)展性良好响蓉。

缺點(diǎn): 
1、策略類會(huì)增多哨毁。 
2枫甲、所有策略類都需要對(duì)外暴露。

使用場(chǎng)景: 
1扼褪、如果在一個(gè)系統(tǒng)里面有許多類想幻,它們之間的區(qū)別僅在于它們的行為,那么使用策略模式可以動(dòng)態(tài)地讓一個(gè)對(duì)象在許多行為中選擇一種行為话浇。 
2脏毯、一個(gè)系統(tǒng)需要?jiǎng)討B(tài)地在幾種算法中選擇一種。 
3幔崖、如果一個(gè)對(duì)象有很多的行為食店,如果不用恰當(dāng)?shù)哪J剑@些行為就只好使用多重的條件選擇語(yǔ)句來(lái)實(shí)現(xiàn)赏寇。

1. 創(chuàng)建接口
public interface Strategy {
   public int doOperation(int num1, int num2);
}
2. 創(chuàng)建接口實(shí)現(xiàn)類
public class OperationAdd implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}

public class OperationSubstract implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}

public class OperationMultiply implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 * num2;
   }
}
3. 創(chuàng)建Context類, 整合接口和實(shí)現(xiàn)類(擁有接口, 實(shí)現(xiàn)動(dòng)態(tài)方法)
public class Context {
   private Strategy strategy;
 
   public Context(Strategy strategy){
      this.strategy = strategy;
   }
 
   public int executeStrategy(int num1, int num2){
      return strategy.doOperation(num1, num2);
   }
}
4. 使用 Context 來(lái)查看當(dāng)它改變策略 Strategy 時(shí)的行為變化
public class StrategyPatternDemo {
   public static void main(String[] args) {
      Context context = new Context(new OperationAdd());    
      System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
 
      context = new Context(new OperationSubstract());      
      System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
 
      context = new Context(new OperationMultiply());    
      System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
   }
}
5. 執(zhí)行程序吉嫩,輸出結(jié)果:
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50

==4-責(zé)任鏈模式-行為型==

image
優(yōu)點(diǎn): 
1、降低耦合度嗅定。它將請(qǐng)求的發(fā)送者和接收者解耦自娩。 
2、簡(jiǎn)化了對(duì)象渠退。使得對(duì)象不需要知道鏈的結(jié)構(gòu)忙迁。 
3脐彩、增強(qiáng)給對(duì)象指派職責(zé)的靈活性。通過(guò)改變鏈內(nèi)的成員或者調(diào)動(dòng)它們的次序姊扔,允許動(dòng)態(tài)地新增或者刪除責(zé)任惠奸。 
4、增加新的請(qǐng)求處理類很方便恰梢。

缺點(diǎn): 
1晨川、不能保證請(qǐng)求一定被接收。 
2删豺、系統(tǒng)性能將受到一定影響,而且在進(jìn)行代碼調(diào)試時(shí)不太方便愧怜,可能會(huì)造成循環(huán)調(diào)用呀页。 
3、可能不容易觀察運(yùn)行時(shí)的特征拥坛,有礙于除錯(cuò)蓬蝶。

使用場(chǎng)景: 
1、有多個(gè)對(duì)象可以處理同一個(gè)請(qǐng)求猜惋,具體哪個(gè)對(duì)象處理該請(qǐng)求由運(yùn)行時(shí)刻自動(dòng)確定丸氛。 
2、在不明確指定接收者的情況下著摔,向多個(gè)對(duì)象中的一個(gè)提交一個(gè)請(qǐng)求缓窜。 
3、可動(dòng)態(tài)指定一組對(duì)象處理請(qǐng)求谍咆。
1. 創(chuàng)建抽象的記錄器類禾锤。
public abstract class AbstractLogger {
   public static int INFO = 1;
   public static int DEBUG = 2;
   public static int ERROR = 3;
 
   protected int level;
 
   //責(zé)任鏈中的下一個(gè)元素
   protected AbstractLogger nextLogger;
 
   public void setNextLogger(AbstractLogger nextLogger){
      this.nextLogger = nextLogger;
   }
 
   public void logMessage(int level, String message){
      if(this.level <= level){
         write(message);
      }
      if(nextLogger !=null){
         nextLogger.logMessage(level, message);
      }
   }
 
   abstract protected void write(String message);
   
}
2. 創(chuàng)建擴(kuò)展了該記錄器類的實(shí)體類。
public class ConsoleLogger extends AbstractLogger {
 
   public ConsoleLogger(int level){
      this.level = level;
   }
 
   @Override
   protected void write(String message) {    
      System.out.println("Standard Console::Logger: " + message);
   }
}

public class ErrorLogger extends AbstractLogger {
 
   public ErrorLogger(int level){
      this.level = level;
   }
 
   @Override
   protected void write(String message) {    
      System.out.println("Error Console::Logger: " + message);
   }
}

public class FileLogger extends AbstractLogger {
 
   public FileLogger(int level){
      this.level = level;
   }
 
   @Override
   protected void write(String message) {    
      System.out.println("File::Logger: " + message);
   }
}
3. 創(chuàng)建不同類型的記錄器摹察。賦予它們不同的錯(cuò)誤級(jí)別恩掷,并在每個(gè)記錄器中設(shè)置下一個(gè)記錄器。每個(gè)記錄器中的下一個(gè)記錄器代表的是鏈的一部分供嚎。
public class ChainPatternDemo {
   
   private static AbstractLogger getChainOfLoggers(){
 
      AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
      AbstractLogger fileLogger = new FileLogger(AbstractLogger.DEBUG);
      AbstractLogger consoleLogger = new ConsoleLogger(AbstractLogger.INFO);
 
      errorLogger.setNextLogger(fileLogger);
      fileLogger.setNextLogger(consoleLogger);
 
      return errorLogger;  
   }
 
   public static void main(String[] args) {
      AbstractLogger loggerChain = getChainOfLoggers();
 
      loggerChain.logMessage(AbstractLogger.INFO, 
         "This is an information.");
 
      loggerChain.logMessage(AbstractLogger.DEBUG, 
         "This is an debug level information.");
 
      loggerChain.logMessage(AbstractLogger.ERROR, 
         "This is an error information.");
   }
}
4. 執(zhí)行程序黄娘,輸出結(jié)果:
Standard Console::Logger: This is an information.
File::Logger: This is an debug level information.
Standard Console::Logger: This is an debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.

==5-狀態(tài)模式-行為型==

image
優(yōu)點(diǎn): 
1、封裝了轉(zhuǎn)換規(guī)則克滴。 
2逼争、枚舉可能的狀態(tài),在枚舉狀態(tài)之前需要確定狀態(tài)種類劝赔。 
3氮凝、將所有與某個(gè)狀態(tài)有關(guān)的行為放到一個(gè)類中,并且可以方便地增加新的狀態(tài)望忆,只需要改變對(duì)象狀態(tài)即可改變對(duì)象的行為罩阵。 
4竿秆、允許狀態(tài)轉(zhuǎn)換邏輯與狀態(tài)對(duì)象合成一體,而不是某一個(gè)巨大的條件語(yǔ)句塊稿壁。 
5幽钢、可以讓多個(gè)環(huán)境對(duì)象共享一個(gè)狀態(tài)對(duì)象,從而減少系統(tǒng)中對(duì)象的個(gè)數(shù)傅是。

缺點(diǎn): 
1匪燕、狀態(tài)模式的使用必然會(huì)增加系統(tǒng)類和對(duì)象的個(gè)數(shù)。 
2喧笔、狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)都較為復(fù)雜帽驯,如果使用不當(dāng)將導(dǎo)致程序結(jié)構(gòu)和代碼的混亂。 
3书闸、狀態(tài)模式對(duì)"開(kāi)閉原則"的支持并不太好尼变,對(duì)于可以切換狀態(tài)的狀態(tài)模式,增加新的狀態(tài)類需要修改那些負(fù)責(zé)狀態(tài)轉(zhuǎn)換的源代碼浆劲,否則無(wú)法切換到新增狀態(tài)嫌术,而且修改某個(gè)狀態(tài)類的行為也需修改對(duì)應(yīng)類的源代碼。

使用場(chǎng)景: 
1牌借、行為隨狀態(tài)改變而改變的場(chǎng)景度气。 
2、條件膨报、分支語(yǔ)句的代替者磷籍。
1. 創(chuàng)建一個(gè)接口。
public interface State {
   public void doAction(Context context);
}
2. 創(chuàng)建實(shí)現(xiàn)接口的實(shí)體類现柠。
public class StartState implements State {
 
   public void doAction(Context context) {
      System.out.println("Player is in start state");
      context.setState(this); 
   }
 
   public String toString(){
      return "Start State";
   }
}

public class StopState implements State {
 
   public void doAction(Context context) {
      System.out.println("Player is in stop state");
      context.setState(this); 
   }
 
   public String toString(){
      return "Stop State";
   }
}
3. 創(chuàng)建 Context 類择示。
public class Context {
   private State state;
 
   public Context(){
      state = null;
   }
 
   public void setState(State state){
      this.state = state;     
   }
 
   public State getState(){
      return state;
   }
}
4. 使用 Context 來(lái)查看當(dāng)狀態(tài) State 改變時(shí)的行為變化。
public class StatePatternDemo {
   public static void main(String[] args) {
      Context context = new Context();
 
      StartState startState = new StartState();
      startState.doAction(context);
 
      System.out.println(context.getState().toString());
 
      StopState stopState = new StopState();
      stopState.doAction(context);
 
      System.out.println(context.getState().toString());
   }
}
5. 執(zhí)行程序晒旅,輸出結(jié)果:
Player is in start state
Start State
Player is in stop state
Stop State

==6-命令模式-行為型==

image
優(yōu)點(diǎn): 
1栅盲、降低了系統(tǒng)耦合度。 
2废恋、新的命令可以很容易添加到系統(tǒng)中去谈秫。

缺點(diǎn):
使用命令模式可能會(huì)導(dǎo)致某些系統(tǒng)有過(guò)多的具體命令類。

使用場(chǎng)景:
1鱼鼓、GUI 中每一個(gè)按鈕都是一條命令拟烫。 
2、模擬 CMD迄本。
1. 創(chuàng)建訂單接口
public interface Order {
   void execute();
}
2. 創(chuàng)建請(qǐng)求類-股票
public class Stock {
   
   private String name = "ABC";
   private int quantity = 10;
 
   public void buy(){
      System.out.println("Stock [ Name: "+name+", 
         Quantity: " + quantity +" ] bought");
   }
   public void sell(){
      System.out.println("Stock [ Name: "+name+", 
         Quantity: " + quantity +" ] sold");
   }
}
3. 創(chuàng)建訂單實(shí)現(xiàn)類
public class BuyStock implements Order {
   private Stock abcStock;
 
   public BuyStock(Stock abcStock){
      this.abcStock = abcStock;
   }
 
   public void execute() {
      abcStock.buy();
   }
}

public class SellStock implements Order {
   private Stock abcStock;
 
   public SellStock(Stock abcStock){
      this.abcStock = abcStock;
   }
 
   public void execute() {
      abcStock.sell();
   }
}
4. 創(chuàng)建命令調(diào)用類-經(jīng)紀(jì)人
public class Broker {
   private List<Order> orderList = new ArrayList<Order>(); 
 
   public void takeOrder(Order order){
      orderList.add(order);      
   }
 
   public void placeOrders(){
      for (Order order : orderList) {
         order.execute();
      }
      orderList.clear();
   }
}
5. 應(yīng)用
public class CommandPatternDemo {
   public static void main(String[] args) {
      Stock abcStock = new Stock();
 
      BuyStock buyStockOrder = new BuyStock(abcStock);
      SellStock sellStockOrder = new SellStock(abcStock);
 
      Broker broker = new Broker();
      broker.takeOrder(buyStockOrder);
      broker.takeOrder(sellStockOrder);
 
      broker.placeOrders();
   }
}
6. 執(zhí)行程序硕淑,輸出結(jié)果:
Stock [ Name: ABC, Quantity: 10 ] bought
Stock [ Name: ABC, Quantity: 10 ] sold

==2-結(jié)構(gòu)型==

==7-適配器模式-結(jié)構(gòu)型==

image
優(yōu)點(diǎn): 
1、可以讓任何兩個(gè)沒(méi)有關(guān)聯(lián)的類一起運(yùn)行。 
2置媳、提高了類的復(fù)用于樟。 
3、增加了類的透明度拇囊。 
4迂曲、靈活性好

缺點(diǎn): 
1、過(guò)多地使用適配器寥袭,會(huì)讓系統(tǒng)非常零亂路捧,不易整體進(jìn)行把握。比如传黄,明明看到調(diào)用的是 A 接口杰扫,其實(shí)內(nèi)部被適配成了 B 接口的實(shí)現(xiàn),一個(gè)系統(tǒng)如果太多出現(xiàn)這種情況膘掰,無(wú)異于一場(chǎng)災(zāi)難章姓。因此如果不是很有必要,可以不使用適配器炭序,而是直接對(duì)系統(tǒng)進(jìn)行重構(gòu)。 
2.由于 JAVA 至多繼承一個(gè)類苍日,所以至多只能適配一個(gè)適配者類惭聂,而且目標(biāo)類必須是抽象類。

使用場(chǎng)景:
有動(dòng)機(jī)地修改一個(gè)正常運(yùn)行的系統(tǒng)的接口相恃,這時(shí)應(yīng)該考慮使用適配器模式辜纲。
1. 為媒體播放器和更高級(jí)的媒體播放器創(chuàng)建接口。
public interface MediaPlayer {
   public void play(String audioType, String fileName);
}

public interface AdvancedMediaPlayer { 
   public void playVlc(String fileName);
   public void playMp4(String fileName);
}
2. 創(chuàng)建實(shí)現(xiàn)了 AdvancedMediaPlayer 接口的實(shí)體類拦耐。
public class VlcPlayer implements AdvancedMediaPlayer{
   @Override
   public void playVlc(String fileName) {
      System.out.println("Playing vlc file. Name: "+ fileName);      
   }
 
   @Override
   public void playMp4(String fileName) {
      //什么也不做
   }
}

public class Mp4Player implements AdvancedMediaPlayer{
 
   @Override
   public void playVlc(String fileName) {
      //什么也不做
   }
 
   @Override
   public void playMp4(String fileName) {
      System.out.println("Playing mp4 file. Name: "+ fileName);      
   }
}
3. 創(chuàng)建實(shí)現(xiàn)了 MediaPlayer 接口的適配器類耕腾。
public class MediaAdapter implements MediaPlayer {
 
   AdvancedMediaPlayer advancedMusicPlayer;
 
   public MediaAdapter(String audioType){
      if(audioType.equalsIgnoreCase("vlc") ){
         advancedMusicPlayer = new VlcPlayer();       
      } else if (audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer = new Mp4Player();
      }  
   }
 
   @Override
   public void play(String audioType, String fileName) {
      if(audioType.equalsIgnoreCase("vlc")){
         advancedMusicPlayer.playVlc(fileName);
      }else if(audioType.equalsIgnoreCase("mp4")){
         advancedMusicPlayer.playMp4(fileName);
      }
   }
}
4. 創(chuàng)建實(shí)現(xiàn)了 MediaPlayer 接口的實(shí)體類。
public class AudioPlayer implements MediaPlayer {
   MediaAdapter mediaAdapter; 
 
   @Override
   public void play(String audioType, String fileName) {    
 
      //播放 mp3 音樂(lè)文件的內(nèi)置支持
      if(audioType.equalsIgnoreCase("mp3")){
         System.out.println("Playing mp3 file. Name: "+ fileName);         
      } 
      //mediaAdapter 提供了播放其他文件格式的支持
      else if(audioType.equalsIgnoreCase("vlc") 
         || audioType.equalsIgnoreCase("mp4")){
         mediaAdapter = new MediaAdapter(audioType);
         mediaAdapter.play(audioType, fileName);
      }
      else{
         System.out.println("Invalid media. "+
            audioType + " format not supported");
      }
   }   
}
5. 使用 AudioPlayer 來(lái)播放不同類型的音頻格式杀糯。
public class AdapterPatternDemo {
   public static void main(String[] args) {
      AudioPlayer audioPlayer = new AudioPlayer();
 
      audioPlayer.play("mp3", "beyond the horizon.mp3");
      audioPlayer.play("mp4", "alone.mp4");
      audioPlayer.play("vlc", "far far away.vlc");
      audioPlayer.play("avi", "mind me.avi");
   }
}
6. 執(zhí)行程序扫俺,輸出結(jié)果:
Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported

==8-代理模式-結(jié)構(gòu)型==

image
優(yōu)點(diǎn): 
1、職責(zé)清晰固翰。 
2狼纬、高擴(kuò)展性。 
3骂际、智能化疗琉。

缺點(diǎn):
1、由于在客戶端和真實(shí)主題之間增加了代理對(duì)象歉铝,因此有些類型的代理模式可能會(huì)造成請(qǐng)求的處理速度變慢盈简。 
2、實(shí)現(xiàn)代理模式需要額外的工作,有些代理模式的實(shí)現(xiàn)非常復(fù)雜柠贤。

使用場(chǎng)景:
1香浩、遠(yuǎn)程代理。 
2种吸、虛擬代理弃衍。 
3、Copy-on-Write 代理坚俗。 
4镜盯、保護(hù)(Protect or Access)代理。 
5猖败、Cache代理速缆。 
6、防火墻(Firewall)代理恩闻。 
7艺糜、同步化(Synchronization)代理。 
8幢尚、智能引用(Smart Reference)代理破停。
1. 創(chuàng)建一個(gè)接口。
public interface Image {
   void display();
}
2. 創(chuàng)建實(shí)現(xiàn)接口的實(shí)體類尉剩。
public class RealImage implements Image {
 
   private String fileName;
 
   public RealImage(String fileName){
      this.fileName = fileName;
      loadFromDisk(fileName);
   }
 
   @Override
   public void display() {
      System.out.println("Displaying " + fileName);
   }
 
   private void loadFromDisk(String fileName){
      System.out.println("Loading " + fileName);
   }
}

public class ProxyImage implements Image{
 
   private RealImage realImage;
   private String fileName;
 
   public ProxyImage(String fileName){
      this.fileName = fileName;
   }
 
   @Override
   public void display() {
      if(realImage == null){
         realImage = new RealImage(fileName);
      }
      realImage.display();
   }
}
3. 當(dāng)被請(qǐng)求時(shí)真慢,使用 ProxyImage 來(lái)獲取 RealImage 類的對(duì)象。
public class ProxyPatternDemo {
   
   public static void main(String[] args) {
      Image image = new ProxyImage("test_10mb.jpg");
 
      // 圖像將從磁盤(pán)加載
      image.display(); 
      System.out.println("");
      // 圖像不需要從磁盤(pán)加載
      image.display();  
   }
}
4. 執(zhí)行程序理茎,輸出結(jié)果:
Loading test_10mb.jpg
Displaying test_10mb.jpg

Displaying test_10mb.jpg

==9-裝飾器模式-結(jié)構(gòu)型==

image
優(yōu)點(diǎn):
裝飾類和被裝飾類可以獨(dú)立發(fā)展黑界,不會(huì)相互耦合,裝飾模式是繼承的一個(gè)替代模式皂林,裝飾模式可以動(dòng)態(tài)擴(kuò)展一個(gè)實(shí)現(xiàn)類的功能朗鸠。

缺點(diǎn):
多層裝飾比較復(fù)雜。

使用場(chǎng)景: 
1础倍、擴(kuò)展一個(gè)類的功能烛占。 
2、動(dòng)態(tài)增加功能沟启,動(dòng)態(tài)撤銷扰楼。
1. 創(chuàng)建 Shape 接口
public interface Shape {
   void draw();
}
2. 實(shí)現(xiàn)接口
public class Rectangle implements Shape {
   @Override
   public void draw() {
      System.out.println("Shape: Rectangle");
   }
}

public class Circle implements Shape {
   @Override
   public void draw() {
      System.out.println("Shape: Circle");
   }
}
3. 創(chuàng)建實(shí)現(xiàn)了 Shape 接口的 抽象裝飾類
public abstract class ShapeDecorator implements Shape {
   protected Shape decoratedShape;
   public ShapeDecorator(Shape decoratedShape){
      this.decoratedShape = decoratedShape;
   }
   public void draw(){
      decoratedShape.draw();
   }  
}
4. 創(chuàng)建擴(kuò)展了 ShapeDecorator 類的 實(shí)體裝飾類
public class RedShapeDecorator extends ShapeDecorator {
   public RedShapeDecorator(Shape decoratedShape) {
      super(decoratedShape);     
   }
   @Override
   public void draw() {
      decoratedShape.draw();         
      setRedBorder(decoratedShape);
   }
   private void setRedBorder(Shape decoratedShape){
      System.out.println("Border Color: Red");
   }
}
5. 使用 RedShapeDecorator 來(lái)裝飾 Shape 對(duì)象
public class DecoratorPatternDemo {
   public static void main(String[] args) {
      Shape circle = new Circle();
      Shape redCircle = new RedShapeDecorator(new Circle());
      Shape redRectangle = new RedShapeDecorator(new Rectangle());
      System.out.println("Circle with normal border");
      circle.draw();
      System.out.println("\nCircle of red border");
      redCircle.draw();
      System.out.println("\nRectangle of red border");
      redRectangle.draw();
   }
}
6. 執(zhí)行程序,輸出結(jié)果:
Circle with normal border
Shape: Circle

Circle of red border
Shape: Circle
Border Color: Red

Rectangle of red border
Shape: Rectangle
Border Color: Red

==10-組合模式-結(jié)構(gòu)型==

image
優(yōu)點(diǎn): 
1美浦、高層模塊調(diào)用簡(jiǎn)單弦赖。 
2、節(jié)點(diǎn)自由增加浦辨。

缺點(diǎn):
在使用組合模式時(shí)蹬竖,其葉子和樹(shù)枝的聲明都是實(shí)現(xiàn)類沼沈,而不是接口,違反了依賴倒置原則币厕。

使用場(chǎng)景:
部分列另、整體場(chǎng)景,如樹(shù)形菜單旦装,文件页衙、文件夾的管理。
1. 創(chuàng)建 Employee 類阴绢,該類帶有 Employee 對(duì)象的列表店乐。
public class Employee {
   private String name;
   private String dept;
   private int salary;
   private List<Employee> subordinates;
 
   //構(gòu)造函數(shù)
   public Employee(String name,String dept, int sal) {
      this.name = name;
      this.dept = dept;
      this.salary = sal;
      subordinates = new ArrayList<Employee>();
   }
 
   public void add(Employee e) {
      subordinates.add(e);
   }
 
   public void remove(Employee e) {
      subordinates.remove(e);
   }
 
   public List<Employee> getSubordinates(){
     return subordinates;
   }
 
   public String toString(){
      return ("Employee :[ Name : "+ name 
      +", dept : "+ dept + ", salary :"
      + salary+" ]");
   }   
}
2. 使用 Employee 類來(lái)創(chuàng)建和打印員工的層次結(jié)構(gòu)。
public class CompositePatternDemo {
   public static void main(String[] args) {
      Employee CEO = new Employee("John","CEO", 30000);
 
      Employee headSales = new Employee("Robert","Head Sales", 20000);
 
      Employee headMarketing = new Employee("Michel","Head Marketing", 20000);
 
      Employee clerk1 = new Employee("Laura","Marketing", 10000);
      Employee clerk2 = new Employee("Bob","Marketing", 10000);
 
      Employee salesExecutive1 = new Employee("Richard","Sales", 10000);
      Employee salesExecutive2 = new Employee("Rob","Sales", 10000);
 
      CEO.add(headSales);
      CEO.add(headMarketing);
 
      headSales.add(salesExecutive1);
      headSales.add(salesExecutive2);
 
      headMarketing.add(clerk1);
      headMarketing.add(clerk2);
 
      //打印該組織的所有員工
      System.out.println(CEO); 
      for (Employee headEmployee : CEO.getSubordinates()) {
         System.out.println(headEmployee);
         for (Employee employee : headEmployee.getSubordinates()) {
            System.out.println(employee);
         }
      }        
   }
}
3. 執(zhí)行程序呻袭,輸出結(jié)果為:
Employee :[ Name : John, dept : CEO, salary :30000 ]
Employee :[ Name : Robert, dept : Head Sales, salary :20000 ]
Employee :[ Name : Richard, dept : Sales, salary :10000 ]
Employee :[ Name : Rob, dept : Sales, salary :10000 ]
Employee :[ Name : Michel, dept : Head Marketing, salary :20000 ]
Employee :[ Name : Laura, dept : Marketing, salary :10000 ]
Employee :[ Name : Bob, dept : Marketing, salary :10000 ]

==11-外觀模式-結(jié)構(gòu)型==

image
優(yōu)點(diǎn): 
1眨八、減少系統(tǒng)相互依賴。 
2左电、提高靈活性廉侧。 
3、提高了安全性篓足。

缺點(diǎn):
不符合開(kāi)閉原則段誊,如果要改東西很麻煩,繼承重寫(xiě)都不合適栈拖。

使用場(chǎng)景: 
1连舍、為復(fù)雜的模塊或子系統(tǒng)提供外界訪問(wèn)的模塊。 
2辱魁、子系統(tǒng)相對(duì)獨(dú)立烟瞧。 
3诗鸭、預(yù)防低水平人員帶來(lái)的風(fēng)險(xiǎn)疫粥。
1. 創(chuàng)建一個(gè)接口纵潦。
public interface Shape {
   void draw();
}
2. 創(chuàng)建實(shí)現(xiàn)接口的實(shí)體類。
public class Rectangle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Rectangle::draw()");
   }
}

public class Square implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Square::draw()");
   }
}

public class Circle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Circle::draw()");
   }
}
3. 創(chuàng)建一個(gè)外觀類。
public class ShapeMaker {
   private Shape circle;
   private Shape rectangle;
   private Shape square;
 
   public ShapeMaker() {
      circle = new Circle();
      rectangle = new Rectangle();
      square = new Square();
   }
 
   public void drawCircle(){
      circle.draw();
   }
   public void drawRectangle(){
      rectangle.draw();
   }
   public void drawSquare(){
      square.draw();
   }
}
4. 使用該外觀類畫(huà)出各種類型的形狀逢慌。
public class FacadePatternDemo {
   public static void main(String[] args) {
      ShapeMaker shapeMaker = new ShapeMaker();
 
      shapeMaker.drawCircle();
      shapeMaker.drawRectangle();
      shapeMaker.drawSquare();      
   }
}
5. 執(zhí)行程序,輸出結(jié)果:
Circle::draw()
Rectangle::draw()
Square::draw()

==3-創(chuàng)建型==

==12-單例模式-創(chuàng)建型==

優(yōu)點(diǎn):
1魁巩、在內(nèi)存里只有一個(gè)實(shí)例牺汤,減少了內(nèi)存的開(kāi)銷,尤其是頻繁的創(chuàng)建和銷毀實(shí)例(比如管理學(xué)院首頁(yè)頁(yè)面緩存)妓盲。
2杂拨、避免對(duì)資源的多重占用(比如寫(xiě)文件操作)。

缺點(diǎn):
沒(méi)有接口悯衬,不能繼承弹沽,與單一職責(zé)原則沖突,一個(gè)類應(yīng)該只關(guān)心內(nèi)部邏輯,而不關(guān)心外面怎么樣來(lái)實(shí)例化策橘。

使用場(chǎng)景:
1炸渡、要求生產(chǎn)唯一序列號(hào)。
2丽已、WEB 中的計(jì)數(shù)器蚌堵,不用每次刷新都在數(shù)據(jù)庫(kù)里加一次,用單例先緩存起來(lái)沛婴。
3吼畏、創(chuàng)建的一個(gè)對(duì)象需要消耗的資源過(guò)多,比如 I/O 與數(shù)據(jù)庫(kù)的連接等瘸味。

12.1 靜態(tài)內(nèi)部類(static inner class)

是否 Lazy 初始化:是
是否多線程安全:是

public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}

12.2 雙檢鎖/雙重校驗(yàn)鎖(DCL, double-checked locking)

是否 Lazy 初始化:是
是否多線程安全:是
public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

==13-工廠模式-創(chuàng)建型==

13.1 簡(jiǎn)單工廠

image
優(yōu)點(diǎn): 
1宫仗、一個(gè)調(diào)用者想創(chuàng)建一個(gè)對(duì)象,只要知道其名稱就可以了旁仿。 
2藕夫、擴(kuò)展性高,如果想增加一個(gè)產(chǎn)品枯冈,只要擴(kuò)展一個(gè)工廠類就可以毅贮。 
3、屏蔽產(chǎn)品的具體實(shí)現(xiàn)尘奏,調(diào)用者只關(guān)心產(chǎn)品的接口滩褥。

缺點(diǎn):
每次增加一個(gè)產(chǎn)品時(shí),都需要增加一個(gè)具體類和對(duì)象實(shí)現(xiàn)工廠炫加,使得系統(tǒng)中類的個(gè)數(shù)成倍增加瑰煎,在一定程度上增加了系統(tǒng)的復(fù)雜度,同時(shí)也增加了系統(tǒng)具體類的依賴俗孝。這并不是什么好事酒甸。

使用場(chǎng)景: 
1、日志記錄器:記錄可能記錄到本地硬盤(pán)赋铝、系統(tǒng)事件插勤、遠(yuǎn)程服務(wù)器等,用戶可以選擇記錄日志到什么地方革骨。 
2农尖、數(shù)據(jù)庫(kù)訪問(wèn),當(dāng)用戶不知道最后系統(tǒng)采用哪一類數(shù)據(jù)庫(kù)良哲,以及數(shù)據(jù)庫(kù)可能有變化時(shí)盛卡。 
3、設(shè)計(jì)一個(gè)連接服務(wù)器的框架筑凫,需要三個(gè)協(xié)議滑沧,"POP3"喇颁、"IMAP"、"HTTP"嚎货,可以把這三個(gè)作為產(chǎn)品類橘霎,共同實(shí)現(xiàn)一個(gè)接口。
1. 創(chuàng)建一個(gè)接口
public interface Shape {
   void draw();
}
2. 創(chuàng)建實(shí)現(xiàn)接口的實(shí)體類殖属。
public class Rectangle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

public class Square implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

public class Circle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}
3. 創(chuàng)建一個(gè)工廠姐叁,生成基于給定信息的實(shí)體類的對(duì)象。
public class ShapeFactory {
    
   //使用 getShape 方法獲取形狀類型的對(duì)象
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
}
4. 使用該工廠洗显,通過(guò)傳遞類型信息來(lái)獲取實(shí)體類的對(duì)象外潜。
public class FactoryPatternDemo {
 
   public static void main(String[] args) {
      ShapeFactory shapeFactory = new ShapeFactory();
 
      //獲取 Circle 的對(duì)象,并調(diào)用它的 draw 方法
      Shape shape1 = shapeFactory.getShape("CIRCLE");
 
      //調(diào)用 Circle 的 draw 方法
      shape1.draw();
 
      //獲取 Rectangle 的對(duì)象挠唆,并調(diào)用它的 draw 方法
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
 
      //調(diào)用 Rectangle 的 draw 方法
      shape2.draw();
 
      //獲取 Square 的對(duì)象处窥,并調(diào)用它的 draw 方法
      Shape shape3 = shapeFactory.getShape("SQUARE");
 
      //調(diào)用 Square 的 draw 方法
      shape3.draw();
   }
}
5. 執(zhí)行程序,輸出結(jié)果
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.

13.2 抽象工廠

image
優(yōu)點(diǎn):
當(dāng)一個(gè)產(chǎn)品族中的多個(gè)對(duì)象被設(shè)計(jì)成一起工作時(shí)玄组,它能保證客戶端始終只使用同一個(gè)產(chǎn)品族中的對(duì)象滔驾。

缺點(diǎn):
產(chǎn)品族擴(kuò)展非常困難,要增加一個(gè)系列的某一產(chǎn)品俄讹,既要在抽象的 Creator 里加代碼哆致,又要在具體的里面加代碼。

使用場(chǎng)景: 
1患膛、QQ 換皮膚摊阀,一整套一起換。 
2踪蹬、生成不同操作系統(tǒng)的程序胞此。
1. 為形狀創(chuàng)建一個(gè)接口。
public interface Shape {
   void draw();
}
2. 創(chuàng)建實(shí)現(xiàn)接口的實(shí)體類跃捣。
public class Rectangle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

public class Square implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

public class Circle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}
3. 為顏色創(chuàng)建一個(gè)接口漱牵。
public interface Color {
   void fill();
}
4. 創(chuàng)建實(shí)現(xiàn)接口的實(shí)體類。
public class Red implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Red::fill() method.");
   }
}

public class Green implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Green::fill() method.");
   }
}

public class Blue implements Color {
 
   @Override
   public void fill() {
      System.out.println("Inside Blue::fill() method.");
   }
}
5. 為 Color 和 Shape 對(duì)象創(chuàng)建抽象類來(lái)獲取工廠枝缔。
public abstract class AbstractFactory {
   public abstract Color getColor(String color);
   public abstract Shape getShape(String shape) ;
}
6. 創(chuàng)建擴(kuò)展了 AbstractFactory 的工廠類布疙,基于給定的信息生成實(shí)體類的對(duì)象蚊惯。
public class ShapeFactory extends AbstractFactory {
    
   @Override
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }        
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
   
   @Override
   public Color getColor(String color) {
      return null;
   }
}

public class ColorFactory extends AbstractFactory {
    
   @Override
   public Shape getShape(String shapeType){
      return null;
   }
   
   @Override
   public Color getColor(String color) {
      if(color == null){
         return null;
      }        
      if(color.equalsIgnoreCase("RED")){
         return new Red();
      } else if(color.equalsIgnoreCase("GREEN")){
         return new Green();
      } else if(color.equalsIgnoreCase("BLUE")){
         return new Blue();
      }
      return null;
   }
}
7. 創(chuàng)建一個(gè)工廠創(chuàng)造器/生成器類愿卸,通過(guò)傳遞形狀或顏色信息來(lái)獲取工廠截型。
public class FactoryProducer {
   public static AbstractFactory getFactory(String choice){
      if(choice.equalsIgnoreCase("SHAPE")){
         return new ShapeFactory();
      } else if(choice.equalsIgnoreCase("COLOR")){
         return new ColorFactory();
      }
      return null;
   }
}
8. 使用 FactoryProducer 來(lái)獲取 AbstractFactory,通過(guò)傳遞類型信息來(lái)獲取實(shí)體類的對(duì)象宦焦。
public class AbstractFactoryPatternDemo {
   public static void main(String[] args) {
 
      //獲取形狀工廠
      AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
 
      //獲取形狀為 Circle 的對(duì)象
      Shape shape1 = shapeFactory.getShape("CIRCLE");
 
      //調(diào)用 Circle 的 draw 方法
      shape1.draw();
 
      //獲取形狀為 Rectangle 的對(duì)象
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
 
      //調(diào)用 Rectangle 的 draw 方法
      shape2.draw();
      
      //獲取形狀為 Square 的對(duì)象
      Shape shape3 = shapeFactory.getShape("SQUARE");
 
      //調(diào)用 Square 的 draw 方法
      shape3.draw();
 
      //獲取顏色工廠
      AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
 
      //獲取顏色為 Red 的對(duì)象
      Color color1 = colorFactory.getColor("RED");
 
      //調(diào)用 Red 的 fill 方法
      color1.fill();
 
      //獲取顏色為 Green 的對(duì)象
      Color color2 = colorFactory.getColor("Green");
 
      //調(diào)用 Green 的 fill 方法
      color2.fill();
 
      //獲取顏色為 Blue 的對(duì)象
      Color color3 = colorFactory.getColor("BLUE");
 
      //調(diào)用 Blue 的 fill 方法
      color3.fill();
   }
}
9. 執(zhí)行程序顿涣,輸出結(jié)果:
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside Red::fill() method.
Inside Green::fill() method.
Inside Blue::fill() method.
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市酝豪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌孵淘,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瘫证,死亡現(xiàn)場(chǎng)離奇詭異揉阎,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)背捌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)毡庆,“玉大人,你說(shuō)我怎么就攤上這事垮衷」宰梗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵熊泵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我徐许,道長(zhǎng)卒蘸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任恰起,我火速辦了婚禮趾牧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘翘单。我一直安慰自己蹦渣,他們只是感情好貌亭,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著权逗,像睡著了一般冤议。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上堪滨,一...
    開(kāi)封第一講書(shū)人閱讀 49,829評(píng)論 1 290
  • 那天蕊温,我揣著相機(jī)與錄音,去河邊找鬼义矛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛了讨,可吹牛的內(nèi)容都是我干的制轰。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼男杈,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼调俘!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起彩库,我...
    開(kāi)封第一講書(shū)人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤侧巨,失蹤者是張志新(化名)和其女友劉穎鞭达,沒(méi)想到半個(gè)月后皇忿,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體坦仍,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年幔荒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了梳玫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡姚垃,死狀恐怖盼忌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谦纱,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布川慌,位于F島的核電站祠乃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏忍饰。R本人自食惡果不足惜寺庄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望斗塘。 院中可真熱鬧,春花似錦于置、人聲如沸贞岭。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至乳讥,卻和暖如春廓俭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背研乒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工告嘲, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人橄唬。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像隆判,于是被迫代替她去往敵國(guó)和親僧界。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容