狀態(tài)模式

在軟件開發(fā)過程中,應用程序中的有些對象可能會根據(jù)不同的情況做出不同的行為经柴,我們把這種對象稱為有狀態(tài)的對象猴娩,而把影響對象行為的一個或多個動態(tài)變化的屬性稱為狀態(tài)。當有狀態(tài)的對象與外部事件產(chǎn)生互動時饿肺,其內(nèi)部狀態(tài)會發(fā)生改變蒋困,從而使得其行為也隨之發(fā)生改變。如人的情緒有高興的時候和傷心的時候敬辣,不同的情緒有不同的行為雪标,當然外界也會影響其情緒變化零院。

對這種有狀態(tài)的對象編程,傳統(tǒng)的解決方案是:將這些所有可能發(fā)生的情況全都考慮到村刨,然后使用 if-else 語句來做狀態(tài)判斷告抄,再進行不同情況的處理。但當對象的狀態(tài)很多時嵌牺,程序會變得很復雜打洼。而且增加新的狀態(tài)要添加新的 if-else 語句,這違背了“開閉原則”逆粹,不利于程序的擴展拟蜻。

以上問題如果采用“狀態(tài)模式”就能很好地得到解決。狀態(tài)模式的解決思想是:當控制一個對象狀態(tài)轉(zhuǎn)換的條件表達式過于復雜時枯饿,把相關(guān)“判斷邏輯”提取出來酝锅,放到一系列的狀態(tài)類當中,這樣可以把原來復雜的邏輯判斷簡單化奢方。

狀態(tài)模式的定義與特點

狀態(tài)(State)模式的定義:對有狀態(tài)的對象搔扁,把復雜的“判斷邏輯”提取到不同的狀態(tài)對象中,允許狀態(tài)對象在其內(nèi)部狀態(tài)發(fā)生改變時改變其行為蟋字。

狀態(tài)模式是一種對象行為型模式稿蹲,其主要優(yōu)點如下。

  1. 狀態(tài)模式將與特定狀態(tài)相關(guān)的行為局部化到一個狀態(tài)中鹊奖,并且將不同狀態(tài)的行為分割開來苛聘,滿足“單一職責原則”。
  2. 減少對象間的相互依賴忠聚。將不同的狀態(tài)引入獨立的對象中會使得狀態(tài)轉(zhuǎn)換變得更加明確设哗,且減少對象間的相互依賴。
  3. 有利于程序的擴展两蟀。通過定義新的子類很容易地增加新的狀態(tài)和轉(zhuǎn)換网梢。

狀態(tài)模式的主要缺點如下。

  1. 狀態(tài)模式的使用必然會增加系統(tǒng)的類與對象的個數(shù)赂毯。
  2. 狀態(tài)模式的結(jié)構(gòu)與實現(xiàn)都較為復雜战虏,如果使用不當會導致程序結(jié)構(gòu)和代碼的混亂。

狀態(tài)模式的結(jié)構(gòu)與實現(xiàn)

狀態(tài)模式把受環(huán)境改變的對象行為包裝在不同的狀態(tài)對象里党涕,其意圖是讓一個對象在其內(nèi)部狀態(tài)改變的時候烦感,其行為也隨之改變。現(xiàn)在我們來分析其基本結(jié)構(gòu)和實現(xiàn)方法膛堤。

1. 模式的結(jié)構(gòu)

狀態(tài)模式包含以下主要角色手趣。

  1. 環(huán)境(Context)角色:也稱為上下文,它定義了客戶感興趣的接口骑祟,維護一個當前狀態(tài)回懦,并將與狀態(tài)相關(guān)的操作委托給當前狀態(tài)對象來處理气笙。
  2. 抽象狀態(tài)(State)角色:定義一個接口,用以封裝環(huán)境對象中的特定狀態(tài)所對應的行為怯晕。
  3. 具體狀態(tài)(Concrete State)角色:實現(xiàn)抽象狀態(tài)所對應的行為潜圃。

其結(jié)構(gòu)圖如圖 1 所示。

狀態(tài)模式的結(jié)構(gòu)圖

圖1 狀態(tài)模式的結(jié)構(gòu)圖

2. 模式的實現(xiàn)

狀態(tài)模式的實現(xiàn)代碼如下:


1.  package  state;
2.  public class  StatePatternClient
3.  {
4.  public static void main(String[] args)
5.  {       
6.  Context  context=new Context();    //創(chuàng)建環(huán)境 
7.  context.Handle();    //處理請求
8.  context.Handle();
9.  context.Handle();
10.  context.Handle();
11.  }
12.  }
13.  //環(huán)境類
14.  class  Context
15.  {
16.  private State  state;
17.  //定義環(huán)境類的初始狀態(tài)
18.  public Context()
19.  {
20.  this.state=new ConcreteStateA();
21.  }
22.  //設(shè)置新狀態(tài)
23.  public void setState(State  state)
24.  {
25.  this.state=state;
26.  }
27.  //讀取狀態(tài)
28.  public State  getState()
29.  {
30.  return(state);
31.  }
32.  //對請求做處理
33.  public void Handle()
34.  {
35.  state.Handle(this);
36.  }
37.  }
38.  //抽象狀態(tài)類
39.  abstract class  State
40.  {
41.  public abstract void Handle(Context  context);
42.  }
43.  //具體狀態(tài)A類
44.  class  ConcreteStateA extends State
45.  {
46.  public void Handle(Context  context)
47.  {
48.  System.out.println("當前狀態(tài)是 A.");
49.  context.setState(new ConcreteStateB());
50.  }
51.  }
52.  //具體狀態(tài)B類
53.  class  ConcreteStateB extends State
54.  {
55.  public void Handle(Context  context)
56.  {
57.  System.out.println("當前狀態(tài)是 B.");
58.  context.setState(new ConcreteStateA());
59.  }
60.  }

程序運行結(jié)果如下:

<pre class="info-box">當前狀態(tài)是 A.
當前狀態(tài)是 B.
當前狀態(tài)是 A.
當前狀態(tài)是 B.</pre>

狀態(tài)模式的應用實例

【例1】用“狀態(tài)模式”設(shè)計一個學生成績的狀態(tài)轉(zhuǎn)換程序舟茶。

分析:本實例包含了“不及格”“中等”和“優(yōu)秀” 3 種狀態(tài)谭期,當學生的分數(shù)小于 60 分時為“不及格”狀態(tài),當分數(shù)大于等于 60 分且小于 90 分時為“中等”狀態(tài)吧凉,當分數(shù)大于等于 90 分時為“優(yōu)秀”狀態(tài)隧出,我們用狀態(tài)模式來實現(xiàn)這個程序。

首先阀捅,定義一個抽象狀態(tài)類(AbstractState)胀瞪,其中包含了環(huán)境屬性、狀態(tài)名屬性和當前分數(shù)屬性饲鄙,以及加減分方法 addScore(intx) 和檢查當前狀態(tài)的抽象方法 checkState()凄诞;然后,定義“不及格”狀態(tài)類 LowState忍级、“中等”狀態(tài)類 MiddleState 和“優(yōu)秀”狀態(tài)類 HighState帆谍,它們是具體狀態(tài)類,實現(xiàn) checkState() 方法轴咱,負責檢査自己的狀態(tài)汛蝙,并根據(jù)情況轉(zhuǎn)換;最后朴肺,定義環(huán)境類(ScoreContext)窖剑,其中包含了當前狀態(tài)對象和加減分的方法 add(int score),客戶類通過該方法來改變成績狀態(tài)宇挫。圖 2 所示是其結(jié)構(gòu)圖苛吱。

學生成績的狀態(tài)轉(zhuǎn)換程序的結(jié)構(gòu)圖

圖2 學生成績的狀態(tài)轉(zhuǎn)換程序的結(jié)構(gòu)圖

程序代碼如下:


1.  package  state;
2.  public class  ScoreStateTest
3.  {
4.  public static void main(String[] args)
5.  {
6.  ScoreContext  account=new ScoreContext();
7.  System.out.println("學生成績狀態(tài)測試:");
8.  account.add(30);
9.  account.add(40);
10.  account.add(25);
11.  account.add(-15);
12.  account.add(-25);
13.  }
14.  }
15.  //環(huán)境類
16.  class  ScoreContext
17.  {
18.  private AbstractState  state;
19.  ScoreContext()
20.  {
21.  state=new LowState(this);
22.  }
23.  public void setState(AbstractState  state)
24.  {
25.  this.state=state;
26.  }
27.  public AbstractState  getState()
28.  {
29.  return state;
30.  }   
31.  public void add(int score)
32.  {
33.  state.addScore(score);
34.  }
35.  }
36.  //抽象狀態(tài)類
37.  abstract class  AbstractState
38.  {
39.  protected ScoreContext  hj;  //環(huán)境
40.  protected String  stateName; //狀態(tài)名
41.  protected int score; //分數(shù)
42.  public abstract void checkState(); //檢查當前狀態(tài)
43.  public void addScore(int x)
44.  {
45.  score+=x;       
46.  System.out.print("加上:"+x+"分,\t當前分數(shù):"+score );
47.  checkState();
48.  System.out.println("分器瘪,\t當前狀態(tài):"+hj.getState().stateName);
49.  }   
50.  }
51.  //具體狀態(tài)類:不及格
52.  class  LowState extends AbstractState
53.  {
54.  public LowState(ScoreContext  h)
55.  {
56.  hj=h;
57.  stateName="不及格";
58.  score=0;
59.  }
60.  public LowState(AbstractState  state)
61.  {
62.  hj=state.hj;
63.  stateName="不及格";
64.  score=state.score;
65.  }
66.  public void checkState()
67.  {
68.  if(score>=90)
69.  {
70.  hj.setState(new HighState(this));
71.  }
72.  else if(score>=60)
73.  {
74.  hj.setState(new MiddleState(this));
75.  }
76.  }   
77.  }
78.  //具體狀態(tài)類:中等
79.  class  MiddleState extends AbstractState
80.  {
81.  public MiddleState(AbstractState  state)
82.  {
83.  hj=state.hj;
84.  stateName="中等";
85.  score=state.score;
86.  }
87.  public void checkState()
88.  {
89.  if(score<60)
90.  {
91.  hj.setState(new LowState(this));
92.  }
93.  else if(score>=90)
94.  {
95.  hj.setState(new HighState(this));
96.  }
97.  }
98.  }
99.  //具體狀態(tài)類:優(yōu)秀
100.  class  HighState extends AbstractState
101.  {
102.  public HighState(AbstractState  state)
103.  {
104.  hj=state.hj;
105.  stateName="優(yōu)秀";
106.  score=state.score;
107.  }           
108.  public void checkState()
109.  {
110.  if(score<60)
111.  {
112.  hj.setState(new LowState(this));
113.  }
114.  else if(score<90)
115.  {
116.  hj.setState(new MiddleState(this));
117.  }
118.  }
119.  }

程序運行結(jié)果如下:

<pre class="info-box">學生成績狀態(tài)測試:
加上:30分, 當前分數(shù):30分绘雁, 當前狀態(tài):不及格
加上:40分橡疼, 當前分數(shù):70分, 當前狀態(tài):中等
加上:25分庐舟, 當前分數(shù):95分欣除, 當前狀態(tài):優(yōu)秀
加上:-15分, 當前分數(shù):80分挪略, 當前狀態(tài):中等
加上:-25分历帚, 當前分數(shù):55分滔岳, 當前狀態(tài):不及格</pre>

【例2】用“狀態(tài)模式”設(shè)計一個多線程的狀態(tài)轉(zhuǎn)換程序。

分析:多線程存在 5 種狀態(tài)挽牢,分別為新建狀態(tài)谱煤、就緒狀態(tài)、運行狀態(tài)禽拔、阻塞狀態(tài)和死亡狀態(tài)刘离,各個狀態(tài)當遇到相關(guān)方法調(diào)用或事件觸發(fā)時會轉(zhuǎn)換到其他狀態(tài),其狀態(tài)轉(zhuǎn)換規(guī)律如圖 3 所示睹栖。

線程狀態(tài)轉(zhuǎn)換圖

圖3 線程狀態(tài)轉(zhuǎn)換圖

現(xiàn)在先定義一個抽象狀態(tài)類(TheadState)硫惕,然后為圖 3 所示的每個狀態(tài)設(shè)計一個具體狀態(tài)類,它們是新建狀態(tài)(New)野来、就緒狀態(tài)(Runnable )恼除、運行狀態(tài)(Running)、阻塞狀態(tài)(Blocked)和死亡狀態(tài)(Dead)曼氛,每個狀態(tài)中有觸發(fā)它們轉(zhuǎn)變狀態(tài)的方法缚柳,環(huán)境類(ThreadContext)中先生成一個初始狀態(tài)(New),并提供相關(guān)觸發(fā)方法搪锣,圖 4 所示是線程狀態(tài)轉(zhuǎn)換程序的結(jié)構(gòu)圖秋忙。

線程狀態(tài)轉(zhuǎn)換程序的結(jié)構(gòu)圖

圖4 線程狀態(tài)轉(zhuǎn)換程序的結(jié)構(gòu)圖

程序代碼如下:


1.  package  state;
2.  public class  ThreadStateTest
3.  {
4.  public static void main(String[] args)
5.  {
6.  ThreadContext  context=new ThreadContext();
7.  context.start();
8.  context.getCPU();
9.  context.suspend();
10.  context.resume();
11.  context.getCPU();
12.  context.stop();
13.  }
14.  }
15.  //環(huán)境類
16.  class  ThreadContext
17.  {
18.  private ThreadState  state;
19.  ThreadContext()
20.  {
21.  state=new New();
22.  }
23.  public void setState(ThreadState  state)
24.  {
25.  this.state=state;
26.  }
27.  public ThreadState  getState()
28.  {
29.  return state;
30.  }   
31.  public void start()
32.  {
33.  ((New) state).start(this);
34.  }
35.  public void getCPU()
36.  {
37.  ((Runnable) state).getCPU(this);
38.  }
39.  public void suspend()
40.  {
41.  ((Running) state).suspend(this);
42.  }
43.  public void stop()
44.  {
45.  ((Running) state).stop(this);
46.  }
47.  public void resume()
48.  {
49.  ((Blocked) state).resume(this);
50.  }
51.  }
52.  //抽象狀態(tài)類:線程狀態(tài)
53.  abstract class  ThreadState
54.  {
55.  protected String  stateName; //狀態(tài)名
56.  }
57.  //具體狀態(tài)類:新建狀態(tài)
58.  class  New extends ThreadState
59.  {
60.  public New()
61.  {       
62.  stateName="新建狀態(tài)";
63.  System.out.println("當前線程處于:新建狀態(tài).");   
64.  }
65.  public void start(ThreadContext  hj)
66.  {
67.  System.out.print("調(diào)用start()方法-->");
68.  if(stateName.equals("新建狀態(tài)"))
69.  {
70.  hj.setState(new Runnable());
71.  }
72.  else
73.  {
74.  System.out.println("當前線程不是新建狀態(tài),不能調(diào)用start()方法.");
75.  }
76.  }   
77.  }
78.  //具體狀態(tài)類:就緒狀態(tài)
79.  class  Runnable extends ThreadState
80.  {
81.  public Runnable()
82.  {       
83.  stateName="就緒狀態(tài)";
84.  System.out.println("當前線程處于:就緒狀態(tài).");   
85.  }
86.  public void getCPU(ThreadContext  hj)
87.  {
88.  System.out.print("獲得CPU時間-->");
89.  if(stateName.equals("就緒狀態(tài)"))
90.  {
91.  hj.setState(new Running());
92.  }
93.  else
94.  {
95.  System.out.println("當前線程不是就緒狀態(tài)构舟,不能獲取CPU.");
96.  }
97.  }   
98.  }
99.  //具體狀態(tài)類:運行狀態(tài)
100.  class  Running extends ThreadState
101.  {
102.  public Running()
103.  {       
104.  stateName="運行狀態(tài)";
105.  System.out.println("當前線程處于:運行狀態(tài).");   
106.  }
107.  public void suspend(ThreadContext  hj)
108.  {
109.  System.out.print("調(diào)用suspend()方法-->");
110.  if(stateName.equals("運行狀態(tài)"))
111.  {
112.  hj.setState(new Blocked());
113.  }
114.  else
115.  {
116.  System.out.println("當前線程不是運行狀態(tài)灰追,不能調(diào)用suspend()方法.");
117.  }
118.  }
119.  public void stop(ThreadContext  hj)
120.  {
121.  System.out.print("調(diào)用stop()方法-->");
122.  if(stateName.equals("運行狀態(tài)"))
123.  {
124.  hj.setState(new Dead());
125.  }
126.  else
127.  {
128.  System.out.println("當前線程不是運行狀態(tài),不能調(diào)用stop()方法.");
129.  }
130.  }
131.  }
132.  //具體狀態(tài)類:阻塞狀態(tài)
133.  class  Blocked extends ThreadState
134.  {
135.  public Blocked()
136.  {       
137.  stateName="阻塞狀態(tài)";
138.  System.out.println("當前線程處于:阻塞狀態(tài).");   
139.  }
140.  public void resume(ThreadContext  hj)
141.  {
142.  System.out.print("調(diào)用resume()方法-->");
143.  if(stateName.equals("阻塞狀態(tài)"))
144.  {
145.  hj.setState(new Runnable());
146.  }
147.  else
148.  {
149.  System.out.println("當前線程不是阻塞狀態(tài)狗超,不能調(diào)用resume()方法.");
150.  }
151.  }   
152.  }
153.  //具體狀態(tài)類:死亡狀態(tài)
154.  class  Dead extends ThreadState
155.  {
156.  public Dead()
157.  {
158.  stateName="死亡狀態(tài)";
159.  System.out.println("當前線程處于:死亡狀態(tài).");   
160.  }   
161.  }

程序運行結(jié)果如下:

<pre class="info-box">當前線程處于:新建狀態(tài).
調(diào)用start()方法-->當前線程處于:就緒狀態(tài).
獲得CPU時間-->當前線程處于:運行狀態(tài).
調(diào)用suspend()方法-->當前線程處于:阻塞狀態(tài).
調(diào)用resume()方法-->當前線程處于:就緒狀態(tài).
獲得CPU時間-->當前線程處于:運行狀態(tài).
調(diào)用stop()方法-->當前線程處于:死亡狀態(tài).</pre>

狀態(tài)模式的應用場景

通常在以下情況下可以考慮使用狀態(tài)模式弹澎。

  • 當一個對象的行為取決于它的狀態(tài),并且它必須在運行時根據(jù)狀態(tài)改變它的行為時努咐,就可以考慮使用狀態(tài)模式苦蒿。
  • 一個操作中含有龐大的分支結(jié)構(gòu),并且這些分支決定于對象的狀態(tài)時渗稍。

狀態(tài)模式的擴展

在有些情況下佩迟,可能有多個環(huán)境對象需要共享一組狀態(tài),這時需要引入享元模式竿屹,將這些具體狀態(tài)對象放在集合中供程序共享报强,其結(jié)構(gòu)圖如圖 5 所示。

共享狀態(tài)模式的結(jié)構(gòu)圖

圖5 共享狀態(tài)模式的結(jié)構(gòu)圖

分析:共享狀態(tài)模式的不同之處是在環(huán)境類中增加了一個 HashMap 來保存相關(guān)狀態(tài)拱燃,當需要某種狀態(tài)時可以從中獲取秉溉,其程序代碼如下:


package  state;
 import  java.util.HashMap;
 public class  FlyweightStatePattern
{
 public static void main(String[] args)
 {
ShareContext  context=new ShareContext(); //創(chuàng)建環(huán)境 
context.Handle(); //處理請求
context.Handle();
context.Handle();
context.Handle();
  }
 }
 //環(huán)境類
  class  ShareContext
 {
 private ShareState  state;
  private HashMap<String, ShareState>  stateSet=new HashMap<String, ShareState>();
 public ShareContext()
  {
 state=new ConcreteState1();
 stateSet.put("1", state);
 state=new ConcreteState2();
 stateSet.put("2", state);
 state=getState("1");
 }
 //設(shè)置新狀態(tài)
 public void setState(ShareState  state)
{
 this.state=state;
 }
 //讀取狀態(tài)
 public ShareState  getState(String  key)
 {
ShareState  s=(ShareState)stateSet.get(key);
 return s;
}
 //對請求做處理
 public void Handle()
 {
state.Handle(this);
}
}
//抽象狀態(tài)類
abstract class  ShareState
{
public abstract void Handle(ShareContext  context);
}
//具體狀態(tài)1類
class  ConcreteState1 extends ShareState
 {
 public void Handle(ShareContext  context)
{
System.out.println("當前狀態(tài)是: 狀態(tài)1");
context.setState(context.getState("2"));
}
}
//具體狀態(tài)2類
class  ConcreteState2 extends ShareState
 {
public void Handle(ShareContext  context)
 {
 System.out.println("當前狀態(tài)是: 狀態(tài)2");
context.setState(context.getState("1"));
 }
 }

程序運行結(jié)果如下:

當前狀態(tài)是: 狀態(tài)1
當前狀態(tài)是: 狀態(tài)2
當前狀態(tài)是: 狀態(tài)1
當前狀態(tài)是: 狀態(tài)2

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子召嘶,更是在濱河造成了極大的恐慌父晶,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弄跌,死亡現(xiàn)場離奇詭異甲喝,居然都是意外死亡,警方通過查閱死者的電腦和手機碟绑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門俺猿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人格仲,你說我怎么就攤上這事押袍。” “怎么了凯肋?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵谊惭,是天一觀的道長。 經(jīng)常有香客問我侮东,道長圈盔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任悄雅,我火速辦了婚禮驱敲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宽闲。我一直安慰自己众眨,他們只是感情好,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布容诬。 她就那樣靜靜地躺著娩梨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪览徒。 梳的紋絲不亂的頭發(fā)上狈定,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機與錄音习蓬,去河邊找鬼纽什。 笑死,一個胖子當著我的面吹牛友雳,可吹牛的內(nèi)容都是我干的稿湿。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼押赊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起流礁,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤涕俗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后神帅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體再姑,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年找御,在試婚紗的時候發(fā)現(xiàn)自己被綠了元镀。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡霎桅,死狀恐怖栖疑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情滔驶,我是刑警寧澤遇革,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站揭糕,受9級特大地震影響萝快,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜著角,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一揪漩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吏口,春花似錦奄容、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至囚痴,卻和暖如春叁怪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背深滚。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工奕谭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人痴荐。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓血柳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親生兆。 傳聞我的和親對象是個殘疾皇子难捌,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

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