設(shè)計(jì)模式-責(zé)任鏈模式

責(zé)任鏈模式的介紹

? 責(zé)任鏈模式(Iterator Pattren),是行為型設(shè)計(jì)模式之一。什么是“鏈”?我們將多個(gè)節(jié)點(diǎn)首尾相連所構(gòu)成的模型稱(chēng)為鏈,比如生活中常見(jiàn)的鎖鏈,就是由一個(gè)個(gè)圓角長(zhǎng)方形的鐵環(huán)串起來(lái)的結(jié)構(gòu)。對(duì)于鏈?zhǔn)浇Y(jié)構(gòu),每個(gè)節(jié)點(diǎn)都可以被拆開(kāi)再連接,因此,鏈?zhǔn)浇Y(jié)構(gòu)也具有很好的靈活性。將這樣一種結(jié)構(gòu)應(yīng)用于編程領(lǐng)域,將每個(gè)節(jié)點(diǎn)看作是一個(gè)對(duì)象,每個(gè)對(duì)象擁有不同的處理邏輯,將一個(gè)請(qǐng)求從鏈?zhǔn)降氖锥税l(fā)出,沿著鏈的路徑一次傳遞給每一個(gè)節(jié)點(diǎn)對(duì)象,直至有對(duì)象處理這個(gè)請(qǐng)求為止,我們將這樣的一種模式稱(chēng)為責(zé)任鏈模式。

責(zé)任鏈模式的定義

? 使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免了請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有對(duì)象處理它為止。

責(zé)任鏈模式的使用場(chǎng)景

  • 多個(gè)對(duì)象可以處理同一請(qǐng)求,但具體由哪個(gè)對(duì)象處理則在運(yùn)行時(shí)動(dòng)態(tài)決定。
  • 在請(qǐng)求處理者不明確的情況下向多個(gè)對(duì)象中的一個(gè)提交一個(gè)請(qǐng)求。
  • 需要?jiǎng)討B(tài)指定一組對(duì)象處理請(qǐng)求。

責(zé)任鏈模式的UML類(lèi)圖

責(zé)任鏈模式類(lèi)圖.png

根據(jù)類(lèi)圖我們可以得出如下一個(gè)責(zé)任鏈模式簡(jiǎn)化版通用模式代碼。

//抽象處理類(lèi)
public abstract class Handler {
    protected Handler successor; //下一個(gè)節(jié)點(diǎn)的處理者
    /**
     * 請(qǐng)求處理
     * @param conditon 請(qǐng)求條件
     */
    public abstract void handlerRequest(String conditon);
}

//具體的處理者1
public class ConcreteHandler1 extends Handler {

    @Override
    public void handlerRequest(String conditon) {
        if (conditon.equals("ConcreteHandler1")) {
            System.out.println("ConcreteHandler1 handler");
        } else {
            successor.handlerRequest(conditon);
        }
    }
}


//具體處理者2
public class ConcreteHandler2 extends Handler {

    @Override
    public void handlerRequest(String conditon) {
        if (conditon.equals("ConcreteHandler2")) {
            System.out.println("ConcreteHandler2 handler");
        } else {
            successor.handlerRequest(conditon);
        }
    }
}

//客戶類(lèi) 
public class Client {
    @Test
    public void test() {
        //構(gòu)造一個(gè)ConcreteHandler1對(duì)象
        ConcreteHandler1 handler1 = new ConcreteHandler1();

        //構(gòu)造一個(gè)ConcreteHandler2對(duì)象
        ConcreteHandler2 handler2 = new ConcreteHandler2();

        //設(shè)置handler1的下一個(gè)節(jié)點(diǎn)
        handler1.successor = handler2;

        //設(shè)置handler2的下一個(gè)節(jié)點(diǎn)
        handler2.successor = handler1;

        //處理請(qǐng)求
        handler1.handlerRequest("ConcreteHandler2");
    }
}

角色介紹

  • Handler :抽象處理者角色,聲明一個(gè)請(qǐng)求處理的方法,并在其中保持一個(gè)對(duì)下一個(gè)處理節(jié)Handler 對(duì)象的引用。
  • ConcreteHandler :具體的處理者對(duì)請(qǐng)求進(jìn)行處理 ,如果不能處理則將該請(qǐng)求轉(zhuǎn)發(fā)給下一個(gè)節(jié)點(diǎn)上的處理對(duì)象。

上面我們說(shuō)這個(gè)一個(gè)簡(jiǎn)化版的通用模板代碼,為什么這個(gè)說(shuō)呢?因?yàn)閷?duì)于請(qǐng)求來(lái)說(shuō),其形式是固定的,就是一個(gè)字符串,而判斷一個(gè)節(jié)點(diǎn)上的對(duì)象是否能夠處理該請(qǐng)求的標(biāo)志,則是該字符串是否與之匹配。然而 在大多數(shù)情況下,責(zé)任鏈中的請(qǐng)求和對(duì)應(yīng)的處理規(guī)則是不盡相同的,在這種情況下可以將請(qǐng)求進(jìn)行封裝,同時(shí)對(duì)請(qǐng)求的處理規(guī)則也進(jìn)行封裝作為一個(gè)獨(dú)立的對(duì)象,類(lèi)圖如下所示:


責(zé)任鏈模式封裝類(lèi)圖.png

首先我們看下AbstractHandler 抽象處理者,其聲明了處理者對(duì)象處理請(qǐng)求的方法和獲取處理級(jí)別的方法,并對(duì)具體的處理轉(zhuǎn)發(fā)邏輯進(jìn)行了實(shí)現(xiàn)。

public abstract class AbstractHandler {
    
    protected AbstractHandler nextHandler;
    
    public final void handleRequest(AbstractRequest request){
        //判斷當(dāng)前處理者對(duì)象的處理級(jí)別是否與請(qǐng)求者的處理級(jí)別一致
        if (getHandleLevel()==request.getHandleLevel()){
            handle(request);
        }else {
            //否則將請(qǐng)求對(duì)象轉(zhuǎn)發(fā)給下一個(gè)節(jié)點(diǎn)上的請(qǐng)求對(duì)象
            if (nextHandler!=null){
                nextHandler.handleRequest(request);
            }else {
                //當(dāng)所有處理者對(duì)象均不能處理該請(qǐng)求輸出
                System.out.println("All of haandler can't handle the request");
            }
        }
    }
    
    /**
     * 獲取處理者對(duì)象的處理級(jí)別
     * @return 處理級(jí)別
     */
    protected abstract int getHandleLevel();

    /**
     * 每個(gè)處理者對(duì)象的具體處理方式
     * @param request 請(qǐng)求者對(duì)象
     */
    protected abstract void handle(AbstractRequest request);
}

在這種情況下我們的責(zé)任轉(zhuǎn)發(fā)邏輯由抽象處理類(lèi)控制,而對(duì)于抽象請(qǐng)求者,其內(nèi)部也聲明了一個(gè)獲取請(qǐng)求級(jí)別的方法,其與抽象處理者中返回的處理級(jí)別保持對(duì)應(yīng),什么級(jí)別的處理邏輯就對(duì)應(yīng)什么樣的請(qǐng)求級(jí)別。

//抽象請(qǐng)求類(lèi)
public abstract class AbstractRequest {
    //處理 對(duì)象
    private Object obj;

    public AbstractRequest(Object obj) {
        this.obj = obj;
    }

    /**
     * 獲取處理的內(nèi)容對(duì)象
     * @return 具體的處理對(duì)象
     */
    public Object getContent(){
        return obj;
    }

    /**
     * 獲取請(qǐng)求級(jí)別
     * @return 請(qǐng)求級(jí)別
     */
    public abstract int getHandleLevel();
}

下面我們分別實(shí)現(xiàn)3個(gè)請(qǐng)求者和3 個(gè)處理者對(duì)象 ,邏輯很簡(jiǎn)單。

public class Request1 extends AbstractRequest {
    public Request1(Object obj) {
        super(obj);
    }

    @Override
    public int getHandleLevel() {
        return 1;
    }
}

public class Request2 extends AbstractRequest {
    public Request2(Object obj) {
        super(obj);
    }

    @Override
    public int getHandleLevel() {
        return 2;
    }
}

public class Request3 extends AbstractRequest {
    public Request3(Object obj) {
        super(obj);
    }

    @Override
    public int getHandleLevel() {
        return 3;
    }
}

處理者

public class Handler1 extends AbstractHandler {
    @Override
    protected int getHandleLevel() {
        return 1;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.println("Handle1 handle request:"+request.getHandleLevel());
    }
}

public class Handler2 extends AbstractHandler {
    @Override
    protected int getHandleLevel() {
        return 2;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.println("Handle2 handle request:"+request.getHandleLevel());
    }
}

public class Handler3 extends AbstractHandler {
    @Override
    protected int getHandleLevel() {
        return 2;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.println("Handle3 handle request:"+request.getHandleLevel());
    }
}

下面是客戶類(lèi)

public class Client {
    @Test
    public void main(){
        //構(gòu)造三個(gè)處理者對(duì)象
        Handler1 handler1 = new Handler1();
        Handler2 handler2 = new Handler2();
        Handler3 handler3 = new Handler3();

        //設(shè)置當(dāng)前處理者對(duì)象的下一個(gè)節(jié)點(diǎn)
        handler1.nextHandler = handler2;
        handler2.nextHandler = handler3;

        //構(gòu)造三個(gè)請(qǐng)求者對(duì)象
        Request1 request1 = new Request1("Request1");
        Request2 request2 = new Request2("Request2");
        Request3 request3 = new Request3("Request3");

        //總是從鏈?zhǔn)降氖锥税l(fā)起請(qǐng)求
        handler1.handleRequest(request1);
        handler2.handleRequest(request2);
        handler1.handleRequest(request3);
    }
}
結(jié)果:
Handle1 handle request:1
Handle2 handle request:2
Handle3 handle request:3

責(zé)任鏈模式的簡(jiǎn)單實(shí)現(xiàn)

舉個(gè)例子:公司安排小明出差,出差回來(lái)后花費(fèi)了近5萬(wàn)元,于是小明第二天上班找組長(zhǎng)申請(qǐng)報(bào)銷(xiāo)費(fèi)用,組長(zhǎng)一看是一筆不小的數(shù)目,他沒(méi)有權(quán)限審批,于是組長(zhǎng)拿著票據(jù)去找部門(mén)主管,主管一看要報(bào)這么多錢(qián),自己權(quán)限只能批5千以下的費(fèi)用,這完全超出了自己的范圍,于是主管又去找經(jīng)理,經(jīng)理一看二話不說(shuō)直接拿著票據(jù)去了老板的辦公室,因?yàn)樗荒芘蝗f(wàn)以下的費(fèi)用,上面的情景就是一個(gè)責(zé)任鏈模式的小例子,每一個(gè)人,準(zhǔn)確的說(shuō)是每一類(lèi)人代表這條鏈上的一個(gè)節(jié)點(diǎn),小明是請(qǐng)求的發(fā)起者,而老板則是出于鏈條頂端的類(lèi),小明在鏈條底端發(fā)起一個(gè)申請(qǐng)報(bào)賬的請(qǐng)求,首先由組長(zhǎng)處理該請(qǐng)求,組長(zhǎng)對(duì)比后發(fā)現(xiàn)自己權(quán)限不夠于是將該請(qǐng)求轉(zhuǎn)發(fā)給位于鏈中的下一個(gè)節(jié)點(diǎn)的主管,主管對(duì)比后也發(fā)現(xiàn)自己的權(quán)限不夠又將該請(qǐng)求轉(zhuǎn)發(fā)給經(jīng)理,而經(jīng)理也基于同樣的原因?qū)⒄?qǐng)求轉(zhuǎn)發(fā)給老板,這樣層層轉(zhuǎn)達(dá)直至請(qǐng)求被處理,從中大家可以看到一個(gè)顯而易見(jiàn)的事,就是至始至終小明只與組長(zhǎng)產(chǎn)生的關(guān)聯(lián),后面具體由誰(shuí)處理的票據(jù),小明并不關(guān)心,唯一在乎的是報(bào)賬的結(jié)果,責(zé)任鏈模式在這里很好地將請(qǐng)求的發(fā)起者與處理者解耦。我們?cè)诖a 中模擬這個(gè)過(guò)程,首先還是先聲明一個(gè)抽象的領(lǐng)導(dǎo)類(lèi)。

//抽象領(lǐng)導(dǎo)者
public abstract class Leader {
    //上一級(jí)領(lǐng)導(dǎo)處理者
    protected Leader nexthandler;

    public void handlerRequest(int money){
        if (money<=limit()) {
            handle(money);
        }else {
            if (nexthandler != null) {
                nexthandler.handle(money);
            }
        }
    }

    /**
     * 自身能審批的額度
     * @return 額度
     */
    public abstract int limit();

    /**
     * 處理報(bào)賬行為
     * @param money 具體金額
     */
    public abstract void handle(int money);
}

在這個(gè)抽象的領(lǐng)導(dǎo)類(lèi)中只做了兩件事,一是定義了兩個(gè)抽象接口方法來(lái)確定一個(gè)領(lǐng)導(dǎo)者應(yīng)有的行為和屬性,而是聲明了一個(gè)處理報(bào)賬請(qǐng)求的方法來(lái)確定當(dāng)前領(lǐng)導(dǎo)是否有能力處理報(bào)賬請(qǐng)求,如果沒(méi)有這個(gè)權(quán)限,則將該請(qǐng)求轉(zhuǎn)發(fā)給上一級(jí)的領(lǐng)導(dǎo)處理,接下來(lái)是各個(gè)領(lǐng)導(dǎo)類(lèi)的實(shí)現(xiàn)。

public class GroupLeader extends Leader {
    @Override
    public int limit() {
        return 1000;
    }

    @Override
    public void handle(int money) {
        System.out.println("組長(zhǎng)審批報(bào)銷(xiāo)"+money +"元");
    }
}

public class Director extends Leader {
    @Override
    public int limit() {
        return 5000;
    }

    @Override
    public void handle(int money) {
        System.out.println("主管審批報(bào)銷(xiāo)"+money +"元");
    }
}

public class Manager extends Leader {
    @Override
    public int limit() {
        return 10000;
    }

    @Override
    public void handle(int money) {
        System.out.println("經(jīng)理審批報(bào)銷(xiāo)"+money +"元");
    }
}

public class Boss extends Leader {
    @Override
    public int limit() {
        return Integer.MAX_VALUE;
    }

    @Override
    public void handle(int money) {
        System.out.println("老板審批報(bào)銷(xiāo)"+money +"元");
    }
}

最后小明從組長(zhǎng)開(kāi)始請(qǐng)求申請(qǐng)報(bào)帳。

    @Test
    public void main() {
        //構(gòu)造各個(gè)領(lǐng)導(dǎo)
        GroupLeader groupLeader = new GroupLeader();
        Director director = new Director();
        Manager manager = new Manager();
        Boss boss = new Boss();
        //設(shè)置上一級(jí)領(lǐng)導(dǎo)處理者
        groupLeader.nexthandler = director;
        director.nexthandler = manager;
        manager.nexthandler = boss;
        //發(fā)起請(qǐng)求
        groupLeader.handlerRequest(50000);
    }
結(jié)果
老板審批報(bào)銷(xiāo)50000元

這里大家可能會(huì)想,可不可以直接越過(guò)組長(zhǎng)找組長(zhǎng)報(bào)賬呢?答案是肯定的,這也是責(zé)任鏈模式的靈活之處,請(qǐng)求的發(fā)起可以從責(zé)任鏈的任何一個(gè)節(jié)點(diǎn)開(kāi)始,同時(shí)也可以改變責(zé)任鏈內(nèi)部的傳遞規(guī)則,如果主管不在,我們完全可以跨過(guò)主管從組長(zhǎng)直接將請(qǐng)求轉(zhuǎn)送給經(jīng)理。

對(duì)于責(zé)任鏈中的一個(gè)處理者對(duì)象,其中只有兩個(gè)行為,一是請(qǐng)求處理,而是將請(qǐng)求轉(zhuǎn)送給下一個(gè)節(jié)點(diǎn),不允許某個(gè)處理者對(duì)象在處理了請(qǐng)求后又將請(qǐng)求轉(zhuǎn)發(fā)給上一個(gè)節(jié)點(diǎn)的情況。對(duì)于一條責(zé)任鏈來(lái)說(shuō),一個(gè)請(qǐng)求最終只有兩種情況,一是被某個(gè)處理對(duì)象所處理,另一個(gè)是所有對(duì)象均未對(duì)其處理,對(duì)于前一個(gè)情況我們稱(chēng)該責(zé)任鏈為純的責(zé)任鏈,對(duì)于后一種情況我們稱(chēng)為不純的責(zé)任鏈,在實(shí)際應(yīng)用中,我們所見(jiàn)到的責(zé)任鏈模式大多為不純的責(zé)任鏈。

責(zé)任鏈模式的實(shí)戰(zhàn)

責(zé)任鏈模式與其說(shuō)實(shí)在Android 中的應(yīng)用倒不如說(shuō)是在Java 中的應(yīng)用,畢竟上層應(yīng)用開(kāi)發(fā)大多都是基于Java 的,而我們的設(shè)計(jì)模式也是針對(duì)Java 而言,Android 中我們可以借鑒責(zé)任鏈模式的思想來(lái)優(yōu)化BroadcastReceiver 使之成為一個(gè)全局的責(zé)任處理者,具體方法很簡(jiǎn)單,我們知道Broadcast 可以分為兩種,一種是Normal Broadcast 普通廣播,另一種是Order Broadcast 有序廣播,普通廣播是異步的,發(fā)出時(shí)可以被所有的接收者收到;而有序廣播則是根據(jù)優(yōu)先級(jí)一次傳播的,直到有接收者將其終止或所有接收者都不終止它,有序廣播的這一特性與我們的責(zé)任鏈模式很想近,通過(guò)它可以實(shí)現(xiàn)一種全局的責(zé)任鏈?zhǔn)录幚恚@里我們創(chuàng)建3個(gè) BroadcastReceiver

public class FirstReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //獲取Intent中附加的限制值
        int limit = intent.getIntExtra("limit", -1001);
        //如果限制值等于1000則處理,否則繼續(xù)轉(zhuǎn)發(fā)給下一個(gè)Receiver
        if (limit!=1000) {
            Bundle bundle = new Bundle();
            bundle.putString("new","Message from FirstReceiver");
            setResultExtras(bundle);
        }else {
            String msg = intent.getStringExtra("msg");
            Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
        }
    }
}

在發(fā)送廣播的時(shí)候我們?cè)?code>Intent 中附加兩個(gè)值,一個(gè)int類(lèi)型的值用于存儲(chǔ)權(quán)限值,另一個(gè)String類(lèi)型的則存儲(chǔ)消息,一個(gè)接收者能否處理本次廣播的唯一條件則是看廣播中所附加的權(quán)限值是否與自身相等如上面FirstReceiver 的處理權(quán)限值是1000;則只有當(dāng)limit =1000時(shí)才會(huì)處理本次廣播,否則在廣播的Intent中在附加一條信息傳遞出去給下一個(gè)接收者。

public class FirstReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //獲取Intent中附加的限制值
        int limit = intent.getIntExtra("limit", -1001);
        //如果限制值等于1000則處理,否則繼續(xù)轉(zhuǎn)發(fā)給下一個(gè)Receiver
        if (limit!=1000) {
            Bundle bundle = new Bundle();
            bundle.putString("new","Message from FirstReceiver");
            setResultExtras(bundle);
        }else {
            String msg = intent.getStringExtra("msg");
            Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
        }
    }
}

public class SecondReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //獲取Intent中附加的限制值
        int limit = intent.getIntExtra("limit", -1001);
        //如果限制值等于1000則處理,否則繼續(xù)轉(zhuǎn)發(fā)給下一個(gè)Receiver
        if (limit!=100) {
            Bundle bundle = new Bundle();
            bundle.putString("new","Message from SecondReceiver");
            setResultExtras(bundle);
        }else {
            String msg = intent.getStringExtra("msg");
            Bundle bundle = getResultExtras(true);
            String str = bundle.getString("new");
            Toast.makeText(context,msg+"<<<>>>" +str, Toast.LENGTH_SHORT).show();
            abortBroadcast();
        }
    }
}

public class ThridReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //獲取Intent中附加的限制值
        int limit = intent.getIntExtra("limit", -1001);
        //如果限制值等于1000則處理,否則繼續(xù)轉(zhuǎn)發(fā)給下一個(gè)Receiver
        if (limit!=10) {
            Bundle bundle = new Bundle();
            bundle.putString("new","Message from ThridReceiver");
            setResultExtras(bundle);
        }else {
            String msg = intent.getStringExtra("msg");
            Bundle bundle = getResultExtras(true);
            String str = bundle.getString("new");
            Toast.makeText(context,msg+"<<<>>>" +str, Toast.LENGTH_SHORT).show();
            abortBroadcast();
        }
    }
}

最后我們還要在清單文件聲明3個(gè)Receiver,并設(shè)定對(duì)應(yīng)的權(quán)限值。

        <receiver android:name=".FirstReceiver" android:exported="false">
            <intent-filter android:priority="1000">
                <action android:name="ORDER_BROADCAST" />
            </intent-filter>
        </receiver>
        <receiver android:name=".SecondReceiver" android:exported="false">
            <intent-filter android:priority="100">
                <action android:name="ORDER_BROADCAST" />
            </intent-filter>
        </receiver>
        <receiver android:name=".ThridReceiver" android:exported="false">
            <intent-filter android:priority="10">
                <action android:name="ORDER_BROADCAST" />
            </intent-filter>
        </receiver>

完成后,我們?cè)谝粋€(gè)Activity中發(fā)送一個(gè)廣播

        Intent intent = new Intent();
        intent.setAction("ORDER_BROADCAST");
        intent.putExtra("limit",1000);
        intent.putExtra("msg","Message from MainActivity");
        sendOrderedBroadcast(intent,null);

這里將limit 設(shè)置為100 ,也就是說(shuō)只有SecondReceiver才會(huì)處理它。

總結(jié)

  • 優(yōu)點(diǎn):可以對(duì)請(qǐng)求者和處理者關(guān)系解耦,提高代碼的靈活性。
  • 缺點(diǎn):對(duì)鏈中請(qǐng)求處理者的遍歷,如果處理者太多,那么遍歷必定會(huì)影響性能,特別是在一些遞歸調(diào)用中。

Demo

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

參考

《Android源碼設(shè)計(jì)模式》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,071評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,409評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,569評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,360評(píng)論 6 404
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,895評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,123評(píng)論 0 286
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,643評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,559評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,742評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評(píng)論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,981評(píng)論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,363評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,622評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,354評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,707評(píng)論 2 370

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

  • 目錄 本文的結(jié)構(gòu)如下: 引言 什么是責(zé)任鏈模式 模式的結(jié)構(gòu) 典型代碼 代碼示例 純與不純的責(zé)任鏈模式 優(yōu)點(diǎn)和缺點(diǎn) ...
    w1992wishes閱讀 1,263評(píng)論 4 14
  • 定義 責(zé)任鏈模式是一種對(duì)象的行為模式。在責(zé)任鏈模式中,很多對(duì)象由每一個(gè)對(duì)象對(duì)其下家的引用而連接起來(lái)形成一條鏈。請(qǐng)求...
    步積閱讀 2,067評(píng)論 1 5
  • 今天來(lái)說(shuō)說(shuō)程序員小猿和產(chǎn)品就關(guān)于需求發(fā)生的故事。前不久,小猿收到了產(chǎn)品的需求。 產(chǎn)品經(jīng)理:小猿,為了迎合大眾屌絲用...
    Jet啟思閱讀 6,401評(píng)論 0 14
  • 前言 Android的設(shè)計(jì)模式系列文章介紹,歡迎關(guān)注,持續(xù)更新中: Android的設(shè)計(jì)模式-設(shè)計(jì)模式的六大原則一...
    四月葡萄閱讀 9,521評(píng)論 5 20
  • 游戲:游樂(lè),玩耍;娛樂(lè)活動(dòng)。伴我良久,分分合合,合合分分。最終,在手機(jī)里批了一塊地給游戲,好讓它安身立命。我與游戲...
    窗外_6ac6閱讀 197評(píng)論 2 1