cocos2d-x中的設(shè)計(jì)模式

本文由子龍山人原創(chuàng),原文鏈接:http://www.zilongshanren.com/cocos2d-x-design-pattern-singleton1/


cocos2d-x 官網(wǎng): http://www.cocos.com/docs/html5/v3/singleton-objs/zh.html

1.Cocos2D-x中的單例如下:


CCDirector ,CCTextureCache, CCSpriteFrameCache, CCAnimationCache, CCUserDefault, CCNotificationCenter刹碾, CCShaderCache, CCScriptEngineManager, CCFileUtils香罐, SimleAudioEngie

為什么會(huì)存在這樣一些單例呢德崭?

CCDirector單例:

它負(fù)責(zé)管理初始化OpenGL渲染窗口以及游戲場景的流程控制阶捆,它是cocos2dx游戲開發(fā)中必不可少的類之一双肤。

為什么要把此類設(shè)計(jì)成單例對(duì)象呢杉适?
因?yàn)橄夷簦粋€(gè)游戲只需要有一個(gè)游戲窗口就夠了鸟辅,所以,只需要初始化一次OpenGL渲染窗口莺葫。而且場景的流程控制功能匪凉,也只需要存在一個(gè)這樣的場景控制對(duì)象即可。為了保證CCDirector類只存在一個(gè)實(shí)例對(duì)象捺檬,就必須使用單例模式再层。

CCTextureCache單例:

此類主要負(fù)責(zé)加載游戲當(dāng)中所需要的紋理圖片資源,這些資源加載好以后堡纬,就可以一直保留在內(nèi)存里面聂受,當(dāng)下次再需要使用此紋理的時(shí)候,直接返回相應(yīng)的紋理對(duì)象引用就可以了烤镐,無需再重復(fù)加載蛋济。當(dāng)然,這樣做可能會(huì)很浪費(fèi)內(nèi)存炮叶,所以cocos2dx采用了一種引用計(jì)數(shù)的方式來管理對(duì)象內(nèi)存碗旅,當(dāng)紋理剛被加載進(jìn)來的時(shí)候,引用計(jì)數(shù)為1悴灵。如果使用此紋理對(duì)象創(chuàng)建一個(gè)精靈扛芽,那么此紋理對(duì)象引用會(huì)加1.如果精靈被釋放,則相應(yīng)的引用計(jì)數(shù)減1.當(dāng)紋理的引用計(jì)數(shù)變?yōu)?的時(shí)候积瞒,紋理所占用的內(nèi)存自然就會(huì)被釋放掉川尖。這也是為什么在收到內(nèi)存警告的時(shí)候,會(huì)調(diào)用CCTextureCache的removeUnusedTextures方法茫孔。此方法會(huì)將所有引用計(jì)數(shù)為1的紋理對(duì)象全部釋放掉叮喳。單從字面上看被芳,Cache,即緩存的意思馍悟。它以犧牲一定的內(nèi)存壓力為代價(jià)畔濒,帶來的是游戲性能的提升。這種cache技術(shù)锣咒,在游戲開發(fā)中比比皆是侵状。注:IO操作對(duì)游戲性能影響非常大,要極力避免R阏Hば帧!

擴(kuò)展:

類似的CCSpriteFrameCache悼嫉、CCAnimationCache和CCShaderCache艇潭,它們也都是緩存類,分別負(fù)責(zé)緩存SpriteFrame戏蔑、Animation和Shader蹋凝。這樣做的原因無非就是為了性能,以空間換時(shí)間.


CCUserDefault單例:

此類主要是用來保存游戲中的數(shù)據(jù)用的总棵,它會(huì)創(chuàng)建一個(gè)xml文件鳍寂,并把用戶自定義的數(shù)據(jù)以key-value的形式存儲(chǔ)到此xml文件中。此類為什么會(huì)變成單例類呢彻舰?原因也很簡單伐割,因?yàn)轭愃七@種操作數(shù)據(jù)文件,或者配置文件的類刃唤,通常只需要在程序運(yùn)行過程中存在一個(gè)實(shí)例即可隔心。

CCNotificationCenter單例:

這是一個(gè)通知中心,它其實(shí)還運(yùn)用了一個(gè)觀察者模式尚胞,這里暫時(shí)不討論硬霍。該通知中心理論上也是只需要一個(gè)就夠了。但是笼裳,cocos2d-x在實(shí)現(xiàn)此單例的時(shí)候唯卖,并沒有將此類的構(gòu)造函數(shù)私有么,我在猜想躬柬,是不是開發(fā)人員有意為之呢拜轨?或者多個(gè)通知中心也有其存在的價(jià)值。這個(gè)大家可以討論一下允青。

CCScriptEngineManager單例:

此類包含一個(gè)實(shí)現(xiàn)了CCScriptEngineProtocl接口的對(duì)象引用橄碾,它可以幫助我們方便地找到LuaEngine對(duì)象。這里單例的作用純粹變成了LuaEngine的一個(gè)全局訪問點(diǎn)了。

為什么不直接把LuaEngine作為單例對(duì)象呢?

是否在某些情況之下法牲,可能需要?jiǎng)?chuàng)建多個(gè)LuaEngine對(duì)象史汗?如果考慮到cocos2d-x還可以同時(shí)支持其它的腳本引擎,那也可以相應(yīng)的把另外的腳本引擎設(shè)計(jì)成單例類拒垃。當(dāng)然停撞,這樣做無疑會(huì)使引擎里面的單例過多〉课停考慮到單例模式近年來被廣大開發(fā)者所詬病戈毒,已將其列入“反模式”。這里引用CCScriptEngineManager單例類谤牡,給其它引擎對(duì)象提供訪問的惟一全局點(diǎn)副硅,這也不失為一個(gè)辦法姥宝。不知我的推測是否正確翅萤?

CCFileUtils類:

該類是一個(gè)工具類。工具類和配置文件類腊满,它們絕大多數(shù)情況也都是設(shè)計(jì)成單例的套么。因?yàn)樗鼈儧]有存在多個(gè)實(shí)例的必要。同時(shí)碳蛋,它們也可以實(shí)現(xiàn)為一組類方法胚泌,這樣無需創(chuàng)建對(duì)象也能夠使用。

SimpleAudioEngine類:

它也被設(shè)計(jì)成了一個(gè)單例類肃弟。因?yàn)樗峁┙o了開發(fā)人員最簡單的聲音操作接口玷室,可以方便地處理游戲中的背景音樂和音效。此類同時(shí)還應(yīng)用了外觀模式笤受,把CocoDenshion子系統(tǒng)中的復(fù)雜功能給屏蔽起來了穷缤,簡化了客戶端程序員的調(diào)用箩兽。該類為什么要設(shè)計(jì)成單例汗贫,是因?yàn)榈教幎家L問它。設(shè)計(jì)成單例會(huì)很方便部蛇,而且它與其它對(duì)象沒有什么聯(lián)系涯鲁,不好使用對(duì)象組合撮竿。


2.使用單例模式的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):簡單易用,限制一個(gè)類只有一個(gè)實(shí)例髓需,可以減少創(chuàng)建多個(gè)對(duì)象可能會(huì)引起的內(nèi)存問題的風(fēng)險(xiǎn)僚匆,包括內(nèi)存泄漏咧擂、內(nèi)存占用問題檀蹋。

缺點(diǎn):單例模式因?yàn)樘峁┝艘粋€(gè)全局的訪問點(diǎn)俯逾,你可以在程序的任何地方輕而易取地訪問到贸桶,這本身就是一種高耦合的設(shè)計(jì)。一旦單例改變以后桌肴,其它模板都需要修改皇筛。另外,單例模式使得對(duì)象變成了全局的了坠七。學(xué)過面對(duì)對(duì)象編程的人都知道水醋,全局變量是非常邪惡的,要盡量不要使用彪置。而且單例模式會(huì)使得對(duì)象的內(nèi)存在程序結(jié)束之前一直存在拄踪,在一些使用GC的語言里面,這其實(shí)就是一種內(nèi)存泄漏宫蛆,因?yàn)樗鼈冇肋h(yuǎn)都不到釋放。當(dāng)然耀盗,也可以通過提供一些方法來釋放單例對(duì)象所占用的內(nèi)存卦尊,比如前面提到的XXXCache對(duì)象,都有相應(yīng)的Purge方法岂却。最后忿薇,cocos2dx里面實(shí)現(xiàn)的單例裙椭,99%都不是線程安全的。

在討論優(yōu)缺點(diǎn)的時(shí)候署浩,讀者想必也看出來了揉燃,缺點(diǎn)比優(yōu)點(diǎn)多多了。這是給大家提個(gè)醒筋栋,以后使用單例模式的時(shí)候要謹(jǐn)慎,不要濫用抢腐。因?yàn)榇四J阶钊菀妆粸E用捣域。只有真正符合單例模式應(yīng)用場景的時(shí)候,才能考慮逐样。不要為了訪問方便挪捕,就把任何類都弄成單例滞乙,這樣,到最后硬耍,你會(huì)發(fā)現(xiàn)你的程序里面就只剩下一堆單例和工廠了墩朦。此外,單例模式正在消減,比如CCActionManager和CCTouchDispatcher在cocos2d1.0之前也是單例,現(xiàn)在變成了CCDirector類的屬性了凰荚。而且Riq(cocos2d-iphone的作者)也有在郵件中提到燃观,以后CCDirector對(duì)象也會(huì)變成非單例,并且允許一個(gè)游戲中創(chuàng)建多個(gè)游戲窗口便瑟。


3.單例模式的定義

public class Singleton
{
public:
//全局訪問點(diǎn)
static Singleton* SharedSingleton()
{
if(NULL == m_spSingleton)
{
m_spSingleton = new Singleton();
}
return m_spSingleton;
}
private:
static Singleton* m_spSingleton;
Singleton();
Singleton(const Singleton& other);
Singleton& operator=(const Singleton& other);
};
Singleton* Singleton::m_spSingleton = NULL;

注意缆毁,這里只是最基本的實(shí)現(xiàn),它沒有考慮到線程安全到涂,也沒有考慮內(nèi)存釋放脊框。但是,這個(gè)實(shí)現(xiàn)有兩個(gè)最基本的要素践啄。一:定義一個(gè)靜態(tài)變量屿讽,并把構(gòu)造函數(shù)等設(shè)置為私有的昭灵。二:提供一個(gè)全局的訪問點(diǎn)給外部訪問。

4.游戲開發(fā)中如何運(yùn)用此模式呢伐谈?

眾所周知烂完,游戲開發(fā)中離不開游戲數(shù)據(jù)保存和加載。這些數(shù)據(jù)包括關(guān)卡數(shù)據(jù)衩婚、游戲進(jìn)行中的狀態(tài)數(shù)據(jù)等窜护。這樣一些信息很多游戲模塊中都需要訪問,所以可以為之設(shè)置一個(gè)單例對(duì)象非春。我武斷地認(rèn)為柱徙,客戶端游戲開發(fā)中缓屠,至少需要一個(gè)單例對(duì)象。因?yàn)橐粋€(gè)全局的訪問點(diǎn)可以方便很多對(duì)象之間的交互护侮。根據(jù)之前的討論敌完,也可以把一些時(shí)覺需要用到的類引用保存在此單例對(duì)象中,不過只需要保存弱引用即可羊初。使用單例滨溉,最嚴(yán)重的就是怕內(nèi)存泄漏,所以长赞,大家盡量不要把單例類設(shè)計(jì)地太復(fù)雜晦攒,也不要讓它包含過多的動(dòng)態(tài)內(nèi)存管理工作。


二段構(gòu)建模式

所謂二段構(gòu)建得哆,就是指創(chuàng)建對(duì)象時(shí)不是直接通過構(gòu)建函數(shù)來分配內(nèi)存并完成初始化操作脯颜。取而代之的是,構(gòu)造函數(shù)只負(fù)責(zé)分配內(nèi)存贩据,而初始化的工作則由一些名為initXXX的成員方法來完成栋操。然后再定義一些靜態(tài)類方法把這兩個(gè)階段組合起來,完成最終對(duì)象的構(gòu)建饱亮。因?yàn)樵凇禖ocoa設(shè)計(jì)模式》一書中矾芙,把此慣用法稱之為“Two Stage Creation”,即“二段構(gòu)建”近上。因?yàn)榇四J皆赾ocos2d里面被廣泛使用剔宪,所以把該模式也引入過來了。

1.應(yīng)用場景:

二段構(gòu)建在cocos2d-x里面隨處可見戈锻,自從2.0版本以后歼跟,所有的二段構(gòu)建方法的簽名都改成create了。這樣做的好處是一方面統(tǒng)一接口格遭,方便記憶,另一方面是以前的類似Cocoa的命名規(guī)范不適用c++留瞳,容易引起歧義拒迅。下面以CCSprite為類,來具體闡述二段構(gòu)建的過程她倘,請(qǐng)看下列代碼:

//此方法現(xiàn)在已經(jīng)不推薦使用了璧微,將來可能會(huì)刪除
CCSprite* CCSprite::spriteWithFile(const char pszFileName)
{
return CCSprite::create(pszFileName);
}
CCSprite
CCSprite::create(const char *pszFileName)
{
CCSprite *pobSprite = new CCSprite(); //1.第一階段,分配內(nèi)存
if (pobSprite && pobSprite->initWithFile(pszFileName)) //2.第二階段硬梁,初始化
{
pobSprite->autorelease(); //G傲颉!荧止!額外做了內(nèi)存管理的工作屹电。
return pobSprite;
}
CC_SAFE_DELETE(pobSprite);

return NULL;

}

如上面代碼中的注釋所示阶剑,創(chuàng)建一個(gè)sprite明顯被分為兩個(gè)步驟:1.使用new來創(chuàng)建內(nèi)存;2.使用initXXX方法來完成初始化危号。
因?yàn)镃CSprite的構(gòu)造函數(shù)也有初始化的功能牧愁,所以,我們?cè)賮砜纯碈CSprite的構(gòu)建函數(shù)實(shí)現(xiàn):

CCSprite::CCSprite(void)
: m_pobTexture(NULL)
, m_bShouldBeHidden(false)
{
}
很明顯外莲,這個(gè)構(gòu)建函數(shù)所做的初始化工作非常有限猪半,僅僅是在初始化列表里面初始化了m_pobTexture和m_bShouldBeHidden兩個(gè)變量。實(shí)際的初始化工作大部分都放在initXXX系列方法中偷线,大家可以動(dòng)手去查看源代碼磨确。

2.分析為什么要使用此模式?

這種二段構(gòu)建對(duì)于C++程序員來說声邦,其實(shí)有點(diǎn)別扭乏奥。因?yàn)閏++的構(gòu)造函數(shù)在設(shè)計(jì)之初就是用來分配內(nèi)存+初始化對(duì)象的。如果再搞個(gè)二段構(gòu)建翔忽,實(shí)則是多此一舉英融。但是,在objective-c里面是沒有構(gòu)造函數(shù)這一說的歇式,所以驶悟,在Cocoa的編程世界里,二段構(gòu)建被廣泛采用材失。而cocos2d-x當(dāng)初是從cocos2d-iphone移植過來了痕鳍,為了保持最大限度的代碼一致性,所以保留了這種二段構(gòu)建方式龙巨。這樣可以方便移植cocos2d-iphone的游戲笼呆,同時(shí)也方便cocos2d-iphone的程序員快速上手cocos2d-x。不過在后來旨别,由于c++天生不具備oc那種可以指定每一個(gè)參數(shù)的名稱的能力诗赌,所以,cocos2d-x的設(shè)計(jì)者決定使用c++的函數(shù)重載來解決這個(gè)問題秸弛。這也是后來為什么2.0版本以后铭若,都使用create函數(shù)的重載版本了.

雖然接口簽名改掉了,但是本質(zhì)并沒有變化递览,還是使用的二段構(gòu)建叼屠。二段構(gòu)建并沒有什么不好,只是更加突出了對(duì)象需要初始化绞铃。在某種程度上也可以說是一種設(shè)計(jì)強(qiáng)化镜雨。因?yàn)橥洺跏蓟且磺心涿畹腷ug的罪魁禍?zhǔn)住M瑫r(shí)儿捧,二段構(gòu)建出來的對(duì)象都是autorelease的對(duì)象荚坞,而autorelease對(duì)象是使用引用計(jì)數(shù)來管理內(nèi)存的挑宠。客戶端程序員在使用此接口創(chuàng)建對(duì)象的時(shí)候西剥,無需關(guān)心具體實(shí)現(xiàn)細(xì)節(jié)痹栖,只要知道使用create方法可以創(chuàng)建并初始化一個(gè)自動(dòng)釋放內(nèi)存的對(duì)象即可。

在一點(diǎn)瞭空,在《Effective Java》一書中揪阿,也有提到。為每一個(gè)類提供一個(gè)靜態(tài)工廠方法來代替構(gòu)造函數(shù)咆畏,

它有以下三個(gè)優(yōu)點(diǎn):

1.與構(gòu)造函數(shù)不同南捂,靜態(tài)方法有名字,而構(gòu)造函數(shù)只能通過參數(shù)重載旧找。
2.它每次被調(diào)用的時(shí)候溺健,不一定都創(chuàng)建一個(gè)新的對(duì)象。比如Boolean.valueOf(boolean)钮蛛。
3.它還可以返回原類型的子類型對(duì)象鞭缭。
因此,使用二段構(gòu)建的原因有二:
1.兼容性魏颓、歷史遺留原因岭辣。(這也再次印證了一句話,一切系統(tǒng)都是遺留系統(tǒng)甸饱,呵呵)
2.二段構(gòu)建有其自身獨(dú)有的優(yōu)勢沦童。
3.使用此模式的優(yōu)缺點(diǎn)是什么?
優(yōu)點(diǎn):
1.顯示分開內(nèi)存分配和初始化階段叹话,讓初始化地位突出偷遗。因?yàn)槌绦騿T一般不會(huì)忘記分配內(nèi)存,但卻常常忽略初始化的作用驼壶。
2.見上面分析《Effective Java》的第1條:“為每一個(gè)類提供一個(gè)靜態(tài)工廠方法來代替構(gòu)造函數(shù)”
3.除了完成對(duì)象構(gòu)建氏豌,還可以管理對(duì)象內(nèi)存。
缺點(diǎn):
1.不如直接使用構(gòu)造函數(shù)來得直白热凹、明了箩溃,違反直覺,但這個(gè)是相對(duì)的碌嘀。
4.此模式的定義及一般實(shí)現(xiàn)定義:將一個(gè)對(duì)象的構(gòu)建分為兩個(gè)步驟來進(jìn)行:1.分配內(nèi)存 2.初始化它的一般實(shí)現(xiàn)如下:

class Test
{
public:
//靜態(tài)工廠方法
static Test* create()
{
Test *pTest = new Test;
if (pTest && pTest->init()) {
//這里還可以做其它操作,比如cocos2d-x里面管理內(nèi)存
return pTest;
}
return NULL;
}
//
Test()
{
//分配成員變量的內(nèi)存歪架,但不初始化
}
bool init(){
//這里初始化對(duì)象成員
return true;
}
private:
//這里定義數(shù)據(jù)成員
};

5.在游戲開發(fā)中如何運(yùn)用此模式

5.在游戲開發(fā)中如何運(yùn)用此模式這個(gè)也非常簡單股冗,就是今后在使用cocos2d-x的時(shí)候,如果你繼承CCSprite實(shí)現(xiàn)自定義的精靈和蚪,你也需要按照“二段構(gòu)建”的方式止状,為你的類提供一個(gè)靜態(tài)工廠方法烹棉,同時(shí)編寫相應(yīng)的初始化方法。當(dāng)然怯疤,命名規(guī)范最好和cocos2d-x統(tǒng)一浆洗,即靜態(tài)工廠方法為create,而初始化方法為initXXXX集峦。

6.此模式經(jīng)常與哪些模式配合使用

由于此模式在GoF的設(shè)計(jì)模式中并未出現(xiàn)伏社,所以暫時(shí)不討論與其它模式的關(guān)系。最后看看cocos2d-x創(chuàng)始人王哲對(duì)于為什么要設(shè)計(jì)成二段構(gòu)建的看法:“其實(shí)我們?cè)O(shè)計(jì)二段構(gòu)造時(shí)首先考慮其優(yōu)勢而非兼容cocos2d-iphone. 初始化時(shí)會(huì)遇到圖片資源不存在等異常塔淤,而C++構(gòu)造函數(shù)無返回值摘昌,只能用try-catch來處理異常,啟用try-catch會(huì)使編譯后二進(jìn)制文件大不少高蜂,故需要init返回bool值聪黎。Symbian, Bada SDK,objc的alloc + init也都是二階段構(gòu)造”

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末备恤,一起剝皮案震驚了整個(gè)濱河市稿饰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌露泊,老刑警劉巖喉镰,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異滤淳,居然都是意外死亡梧喷,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門脖咐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铺敌,“玉大人,你說我怎么就攤上這事屁擅〕テ荆” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵派歌,是天一觀的道長弯囊。 經(jīng)常有香客問我,道長胶果,這世上最難降的妖魔是什么匾嘱? 我笑而不...
    開封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮早抠,結(jié)果婚禮上霎烙,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好悬垃,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開白布游昼。 她就那樣靜靜地躺著,像睡著了一般尝蠕。 火紅的嫁衣襯著肌膚如雪烘豌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天看彼,我揣著相機(jī)與錄音廊佩,去河邊找鬼。 笑死闲昭,一個(gè)胖子當(dāng)著我的面吹牛罐寨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播序矩,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鸯绿,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了簸淀?” 一聲冷哼從身側(cè)響起瓶蝴,我...
    開封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎租幕,沒想到半個(gè)月后舷手,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡劲绪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年男窟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贾富。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡歉眷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出颤枪,到底是詐尸還是另有隱情汗捡,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布畏纲,位于F島的核電站扇住,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏盗胀。R本人自食惡果不足惜艘蹋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望票灰。 院中可真熱鬧簿训,春花似錦咱娶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽屈糊。三九已至的榛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間逻锐,已是汗流浹背夫晌。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昧诱,地道東北人晓淀。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像盏档,于是被迫代替她去往敵國和親凶掰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

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