JAVA隨筆

           

          使用state pattern替代if else

          大多數開發人員現在還在使用if else的過程結構,曾看過jdonbanq大哥寫的一篇文章,利用command,aop模式替代if else過程結構。當時還不太明白,這幾天看了《重構》第一章的影片租賃案例,感觸頗深。下面我來談一談為什么要用state pattern替代if else,替代if else有什么好處,以及給出詳細代碼怎么替代if else。本文參考jdon的“你還在使用if else嗎?”及《重構》第一章。

          ?

          首先我們模仿影片租賃過程,顧客租憑影片,影片分為兒童片、普通片、新片。根據影片類型及租憑天數價格各不相同(優惠程度不同),用戶累計積分不同。

          ?

          OK ,現在我們使用 if else 表示。

          package ?com.qujingbo.movie;

          /**
          ?*?<p/>?Title:影片基類
          ?*?</p>
          ?*?<p/>?Description:
          ?*?</p>
          ?*?<p/>?Date:2006-10-14?15:47:55
          ?*?</p>
          ?*?
          ?*?
          @author ?EOMS?曲靜波
          ?*?
          @version ?1.0
          ?
          */

          public ? class ?Movie? {

          ?????
          // ?普通片標識
          ????? public ? static ? int ?REGULAR? = ? 1 ;
          ????
          ?????
          // ?新片標識
          ????? public ? static ? int ?NEW_RELEASE? = ? 2 ;
          ????
          ?????
          // ?兒童片標識
          ????? public ? static ? int ?CHILDREN? = ? 3 ;
          ????
          ?????
          /**
          ?????*?獲取租賃影片總價
          ?????*
          ?????*?
          @param ?movieCode
          ?????*?影片類型
          ?????*?
          @param ?days
          ?????*?租憑天數
          ?????*?
          @return ?租賃影片總價
          ?????*?
          @throws ?MovieException
          ?????*?沒有影片類型拋出異常
          ?????
          */

          ?????
          public ? double ?getCharge( int ?movieCode,? int ?days)? throws ?MovieException? {
          ?????
          double ?result? = ? 0 ;
          ?????
          // ?普通片
          ????? if ?(movieCode? == ?Movie.REGULAR)
          ?????
          // ?單價為2
          ????? {
          ?????result?
          = ? 2 ;
          ?????
          // ?如果租賃天數大于2則,則優惠
          ????? if ?(days? > ? 2 )? {
          ?????result?
          += ?(days? - ? 2 )? * ? 1.5 ;
          ?????}

          ?????
          // ?返回總價
          ????? return ?result;
          ?????}

          ?????
          // ?最新發布片
          ????? else ? if ?(movieCode? == ?Movie.NEW_RELEASE)? {
          ?????
          // ?新片沒有優惠,單價為3
          ????? return ?days? * ? 3 ;
          ?????}

          ?????
          // ?兒童片
          ????? else ? if ?(movieCode? == ?Movie.CHILDREN)? {
          ?????
          // ?影片單價
          ?????result? = ? 1.5 ;
          ?????
          // ?如果租賃時間大于3天則做價格優惠
          ????? if ?(days? > ? 3 )? {
          ?????result?
          += ?(days? - ? 3 )? * ? 1.5 ;
          ?????}

          ?????
          // ?返回租賃影片總價
          ????? return ?result;
          ?????}
          ? else
          ?????
          throw ? new ?MovieException( " 影片不存在 " );
          ?????}

          ????
          ?????
          /**
          ?????*?獲取租賃影片積分
          ?????*
          ?????*?
          @param ?movieCode
          ?????*?影片類型
          ?????*?
          @param ?days
          ?????*?租憑天數
          ?????*?
          @return ?租賃影片積分
          ?????*?
          @throws ?MovieException
          ?????*?沒有影片類型拋出異常
          ?????
          */

          ?????
          public ? double ?getIntegral( int ?movieCode,? int ?days)? throws ?MovieException
          ?????
          {
          ?????
          // ?普通片
          ????? if ?(movieCode? == ?Movie.REGULAR)
          ?????
          return ?days? * ? 2 ;
          ?????
          // ?最新發布片
          ????? else ? if ?(movieCode? == ?Movie.NEW_RELEASE)
          ?????
          return ?days? * ? 3 ;
          ?????
          // ?兒童片
          ????? else ? if ?(movieCode? == ?Movie.CHILDREN)
          ?????
          return ?days? * ? 1.5 ;
          ????????????
          else
          ????????????????
          throw ? new ?MovieException( " 影片不存在 " );
          ????
          ????????}

          }


          OK ,我們看一下,現在的 Movie 完全符合租賃需求,通過 getIntegral(int movieCode,int days) getCharge(int movieCode,int days) 來獲得租賃積分及租賃價格。從開閉原則角度來看,如果要添加新的影片類型,我們必須修改 getIntegral(int movieCode,int days) getCharge(int movieCode,int days) 這兩個方法。而若要改變租賃價格、積分的優惠規則時,仍需要修改 getIntegral(int movieCode,int days) getCharge(int movieCode,int days) 方法。現在看來,只有三種影片類型,維護還較方便。而當影片類型較多時,例如 10 種, 100 種影片類型,這樣就是不可以想像的維護。

          ?

          現在我們來看一下,使用 state pattern 來代替 if else 。先來個類圖。

          ?

          ifelse.jpg?

          首先我們建立一個 abstract class Price 做為影片類型的基類,基類中含有兩個 abstract 方法,獲取總價格 getCharge(int days), 獲取總積分 getIntegral(int days) 方法 , 繼承 abstract classPrice 的三個影片類型兒童片 class ChilerenPrice, 普通片 class RegularPrice, 最新片 class NewReleasePrice 。分別實現 getCharge(int days),getIntegral(int days) 方法,實現方法寫入計算價格的優惠方案及積分的方案。當需要修改方案時,我們只需在某個影片類的方法中對應修改就可以。若新增一個影片分類時,我們只需新增一個實現類實現 abstract class Price 類就 OK

          ?

          class Movie 代表影片,其關聯一個 Price 類,而 setPrice(String movieClass) 方法類似于一個工廠類,傳入 movieClass 為包名類名,用 java 反射機制實例化一個具體傳入 movieClass 的影片類型實現類,這樣我們通過這幾行代碼就可以獲得該影片類型的價格和積分。

          Movie?regularMovie? = ? new ?Movie();
          regularMovie.setPrice(Movie.REGULAR);
          System.out.println(
          " 普通影片租賃10天的價格 " + ?regularMovie.getPrice().getCharge( 10 ));
          System.out.println(
          " 普通影片租賃10天的積分 " + ?regularMovie.getPrice().getIntegral( 10 ));

          下面我們給出詳細代碼

          abstract class Price價格基類

          package?com.qujingbo.movie;

          /**
          ?*?<p/>?Title:
          ?*?</p>
          ?*?<p/>?Description:
          ?*?</p>
          ?*?<p/>?Date:2006-10-14?15:48:22
          ?*?</p>
          ?*?
          ?*?
          @author?EOMS?曲靜波
          ?*?
          @version?1.0
          ?
          */

          public?abstract?class?Price?{

          ????
          /**
          ?????*?獲取租賃影片價格需實現該此方法
          ?????*?
          ?????*?
          @param?days
          ?????*????????????租賃天數
          ?????*?
          @return?返回影片價格
          ?????
          */

          ????
          public?abstract?double?getCharge(int?days);

          ????
          /**
          ?????*?獲取租賃影片積分需實現此方法
          ?????*?
          ?????*?
          @param?days
          ?????*????????????租賃天數
          ?????*?
          @return?返回影片積分
          ?????
          */

          ????
          public?abstract?double?getIntegral(int?days);

          }



          兒童片ChildrenPrice類,實現abstract class Price ,實現兒童片租賃總價getCharge(int days)及兒童片租賃積分getIntegral(int days)
          package?com.qujingbo.movie;

          /**
          ?*?<p/>?Title:兒童片租賃積分、價格實現
          ?*?</p>
          ?*?<p/>?Description:
          ?*?</p>
          ?*?<p/>?Date:2006-10-14?15:49:04
          ?*?</p>
          ?*?
          ?*?
          @author?EOMS?曲靜波
          ?*?
          @version?1.0
          ?
          */

          public?class?ChildrenPrice?extends?Price?{

          ????
          /**
          ?????*?兒童片返回租賃積分,兒童片積分規則為:?根據
          ?????
          */

          ????
          public?double?getIntegral(int?days)?{
          ????????
          //?返回租賃影片積分
          ????????return?days?*?1.5;
          ????}


          ????
          /**
          ?????*?兒童片返回租賃價格
          ?????
          */

          ????
          public?double?getCharge(int?days)?{
          ????????
          //?影片單價
          ????????double?result?=?1.5;
          ????????
          //?如果租賃時間大于3天則做價格優惠
          ????????if?(days?>?3)?{
          ????????????result?
          +=?(days?-?3)?*?1.5;
          ????????}

          ????????
          //?返回租賃影片總價
          ????????return?result;
          ????}


          }



          普通片RegularlPrice類,實現abstract class Price ,實現普通片租賃總價getCharge(int days)及普通片租賃積分getIntegral(int days)

          package?com.qujingbo.movie;

          /**
          ?*?<p/>?Title:普通片租賃積分、價格實現
          ?*?</p>
          ?*?<p/>?Description:
          ?*?</p>
          ?*?<p/>?Date:2006-10-14?15:50:10
          ?*?</p>
          ?*?
          ?*?
          @author?EOMS?曲靜波
          ?*?
          @version?1.0
          ?
          */

          public?class?RegularlPrice?extends?Price?{
          ????
          /**
          ?????*?普通片返回租賃積分,普通片積分規則
          ?????
          */

          ????
          public?double?getIntegral(int?days)?{
          ????????
          //?返回租賃影片積分
          ????????return?days?*?2;
          ????}


          ????
          /**
          ?????*?普通片返回租賃價格
          ?????
          */

          ????
          public?double?getCharge(int?days)?{
          ????????
          //?單價為2
          ????????double?result?=?2;
          ????????
          //?如果租賃天數大于2則,則優惠
          ????????if?(days?>?2)?{
          ????????????result?
          +=?(days?-?2)?*?1.5;
          ????????}

          ????????
          //?返回總價
          ????????return?result;
          ????}


          }



          最新發布片
          NewReleasePrice類,實現abstract class Price ,實現最新發布片租賃總價getCharge(int days)及最新發布片租賃積分getIntegral(int days)

          package?com.qujingbo.movie;

          /**
          ?*?<p/>?Title:最新發布片租賃積分、價格實現
          ?*?</p>
          ?*?<p/>?Description:
          ?*?</p>
          ?*?<p/>?Date:2006-10-14?15:48:51
          ?*?</p>
          ?*?
          ?*?
          @author?EOMS?曲靜波
          ?*?
          @version?1.0
          ?
          */

          public?class?NewReleasePrice?extends?Price?{
          ????
          /**
          ?????*?最新發布片返回租賃積分,最新發布片積分規則
          ?????
          */

          ????
          public?double?getIntegral(int?days)?{
          ????????
          //?返回租賃影片積分
          ????????return?days?*?3;
          ????}


          ????
          /**
          ?????*?最新發布片返回租賃價格
          ?????
          */

          ????
          public?double?getCharge(int?days)?{
          ????????
          //?新片沒有優惠,單價為3
          ????????return?days?*?3;
          ????}


          }



          電影Movie類,setPrice(String movieClass)(工廠)方法,通過java反射機制實現movieClass(包名,類名)類。若沒有movieClass這個類,則拋出MovieException異常。

          package?com.qujingbo.movie;

          /**
          ?*?<p/>?Title:影片類
          ?*?</p>
          ?*?<p/>?Description:
          ?*?</p>
          ?*?<p/>?Date:2006-10-14?15:47:55
          ?*?</p>
          ?*?
          ?*?
          @author?EOMS?曲靜波
          ?*?
          @version?1.0
          ?
          */

          public?class?Movie?{
          ????
          //?普通片標識
          ????public?static?String?REGULAR?=?"com.qujingbo.movie.RegularlPrice";

          ????
          //?新片標識
          ????public?static?String?NEW_RELEASE?=?"com.qujingbo.movie.NewReleasePrice";

          ????
          //?兒童片標識
          ????public?static?String?CHILDREN?=?"com.qujingbo.movie.ChildrenPrice";

          ????
          private?Price?price;

          ????
          public?Price?getPrice()?{
          ????????
          return?price;
          ????}


          ????
          /**
          ?????*?確定返回具體某個影片類型的實現類,有點像工廠
          ?????*?
          ?????*?
          @param?movieCode
          ?????*????????????影片類型
          ?????*?
          @throws?MovieException
          ?????*?????????????若無影片類型則拋異常。
          ?????
          */

          ????
          public?void?setPrice(String?movieClass)?throws?MovieException?{
          ????????
          try?{
          ????????????Class?cls?
          =?Class.forName(movieClass);
          ????????????
          this.price?=?(Price)?cls.newInstance();
          ????????}
          ?catch?(Exception?e)?{
          ????????????
          throw?new?MovieException("影片不存在");
          ????????}

          ????}

          }



          給出MovieException源碼。

          package?com.qujingbo.movie;

          /**
          ?*?<p/>?Title:自定義異常
          ?*?</p>
          ?*?<p/>?Description:
          ?*?</p>
          ?*?<p/>?Date:2006-10-14?19:21:08
          ?*?</p>
          ?*?
          ?*?
          @author?EOMS?曲靜波
          ?*?
          @version?1.0
          ?
          */

          public?class?MovieException?extends?Exception?{
          ????
          public?MovieException(String?msg)?{
          ????????
          super(msg);
          ????}

          }

          下面模訪一個顧客租賃影片。

          package?com.qujingbo.movie;

          /**
          ?*?<p/>?Title:
          ?*?</p>
          ?*?<p/>?Description:
          ?*?</p>
          ?*?<p/>?Date:2006-10-14?19:26:23
          ?*?</p>
          ?*?
          ?*?
          @author?EOMS?曲靜波
          ?*?
          @version?1.0
          ?
          */

          public?class?Customer?{
          ????
          /**
          ?????*?消費(測試程序)
          ?????*?
          ?????*?
          @throws?MovieException
          ?????*?????????????若沒有影片,拋出異常
          ?????
          */

          ????
          public?void?consume()?throws?MovieException?{
          ????????
          //?普通電影
          ????????Movie?regularMovie?=?new?Movie();
          ????????regularMovie.setPrice(Movie.REGULAR);
          ????????
          //?最新發布電影
          ????????Movie?newReleaseMovie?=?new?Movie();
          ????????newReleaseMovie.setPrice(Movie.NEW_RELEASE);
          ????????
          //?兒童電影
          ????????Movie?childrenMovie?=?new?Movie();
          ????????childrenMovie.setPrice(Movie.CHILDREN);

          ????????System.out.println(
          "普通影片租賃10天的價格"
          ????????????????
          +?regularMovie.getPrice().getCharge(10));
          ????????System.out.println(
          "最新影片租賃10天的價格"
          ????????????????
          +?newReleaseMovie.getPrice().getCharge(10));
          ????????System.out.println(
          "兒童影片租賃10天的價格"
          ????????????????
          +?childrenMovie.getPrice().getCharge(10));
          ????????
          ????????System.out.println(
          "普通影片租賃10天的積分"
          ????????????????
          +?regularMovie.getPrice().getIntegral(10));
          ????????System.out.println(
          "最新影片租賃10天的積分"
          ????????????????
          +?newReleaseMovie.getPrice().getIntegral(10));
          ????????System.out.println(
          "兒童影片租賃10天的積分"
          ????????????????
          +?childrenMovie.getPrice().getIntegral(10));
          ????????
          ????????
          ????}

          }


          寫一 junit 測試類運行 class Customer consume() 方法。

          package ?com.qujingbo.movie;

          import ?junit.framework.TestCase;

          /**
          ?*?<p/>?Title:junit測試類
          ?*?</p>
          ?*?<p/>?Description:
          ?*?</p>
          ?*?<p/>?Date:2006-10-14?19:32:57
          ?*?</p>
          ?*?
          ?*?
          @author ?EOMS?曲靜波
          ?*?
          @version ?1.0
          ?
          */

          public ? class ?CustomerTest? extends ?TestCase? {

          ????
          private ?Customer?customer? = ? null ;

          ????
          protected ? void ?setUp()? throws ?Exception? {
          ????????
          super .setUp();
          ????????customer?
          = ? new ?Customer();
          ????}


          ????
          protected ? void ?tearDown()? throws ?Exception? {
          ????????
          super .tearDown();
          ????}


          ????
          /*
          ?????*?Test?method?for?'com.qujingbo.movie.Customer.consume()'
          ?????
          */

          ????
          public ? void ?testConsume()? {
          ????????
          try ? {
          ????????????customer.consume();
          ????????}
          ? catch ?(MovieException?e)? {
          ????????????System.out.println(
          " 沒有該類影片 " );
          ????????}

          ????}


          }


          OK 。結果為:

          普通影片租賃 10 天的價格 14.0

          最新影片租賃 10 天的價格 30.0

          兒童影片租賃 10 天的價格 12.0

          普通影片租賃 10 天的積分 20.0

          最新影片租賃 10 天的積分 30.0

          兒童影片租賃 10 天的積分 15.0

          ?

          最后我要說,我們用 OO 表示的租賃過程并不完整,因為顧客不一定只租賃一部影片,而要租賃多部影片,這樣我們缺少一個 Rental (租賃類)。而只是為說明 state pattern 替代 if else ,所以我們沒有添加 Rental (租賃類),若需要參考,請查閱《重構》第一章。 點擊下載源碼.

          ?

          這是我第一次寫技術文章,如果有適當的地方,請各位朋友提出各自見解。

          ?

          email:qujingbo@gmail.com

          posted on 2006-10-15 00:10 曲靜波 閱讀(3911) 評論(22)  編輯  收藏 所屬分類: design pattern

          評論

          # re: 使用state pattern替代if else 2006-10-15 10:28 馬嘉楠

          學習
          不錯,寫得很好!  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-15 10:40 曲靜波

          謝謝支持,我一定會再接再厲!也請有疑義的地方提出來,共同討論.  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-15 10:41 zeroblue

          so good!  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-15 10:54 zeroblue

          嗯,問下,如果使用反射機制,Movie類是否不用聲明靜態變量。
          否則增加新的影片類型,不是還要修改Movie類。
          如果要聲明的話,是否加上final比較好?  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-15 10:57 黃奕福

          思路不錯,感覺就是java的風格,一句話的事情要繞來繞去將pattern,容易搞暈了,還要給生手解釋半天.

          有時候還不如if來得直接了當,符合常理思維,誰都看得明白.呵呵  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-15 11:06 zeroblue

          還是應該pattern吧,這里是以影片類型舉例,可以想象一個大型的影片公司,影片類型肯定非常多,都在一個類里用if else搞,頭可能也比較暈。
          而且類型價格等東西有變更,或減增。維護起來會死人的。  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-15 13:12 kebo

          你這個實例化合適的狀態類是在什么時候啊?
          如果根據客戶端的選擇的話,你還是得if else判斷???  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-15 15:10 曲靜波

          @zeroblue


          嗯,你說的有道理.final應該是加的,我露掉了,不好意思.不過想想的話,如果不定義常量的話,也有很多問題,例如:將來修改類名,或多個地方引用,或手敲類名出錯都是問題.這就看個人看法吧.如果不加常量的話,應該完全符合開閉原則了.你有什么更好的想法嗎?在既符合開閉原則,又符合上面提到的問題.  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-15 15:13 曲靜波

          @kebo
          如果客戶端選擇的話,可以直接傳過來一個類名(如果怕暴露類名,可以使用名值對的形式,例如key=1,value="類名");但可能需要一個配置文件配置.不知道仁兄還其他的辦法嗎?  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-15 18:21 zeroblue

          可否這樣:
          將Movie類聲明為一個接口(感覺Price也聲明為接口比較好),每增加一個Price實現類,就增加一個Movie對應的實現類。這要原來的代碼不需要動,符合開閉原則。Movie接口定義子類必須實現的getCharge()方法。子類實現該方法時會調用對應的Price實現類來計算積分。
          consume類代碼可寫成這樣:
          Movie regularMovie = new RegularMovie();
          Movie newReleaseMovie = new NewReleaseMovie();
          Movie childrenMovie = new ChildrenMovie();
          (不知可行否)
            回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-15 22:44 黑蝙蝠

          問個問題啊 假如我現在分了很多類
          1 喜劇片 2 愛情片 3 動作片 4 恐怖片 5 科幻片
          6 古裝片 7 動畫片 8 戰爭片 9 連續劇 10 其它
          這么多類別 也按照這種模式來做?
          那豈不是有很多class文件
          如果新增類型的時候又怎么辦?  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-16 09:18 曲靜波

          @zeroblue
          Movie regularMovie = new RegularMovie();
          Movie newReleaseMovie = new NewReleaseMovie();
          Movie childrenMovie = new ChildrenMovie();
          至于將Movie聲明一個接口我覺得沒有必要.如果新增的話,就要新增兩個類一個Price實現一個Movie實現類.也沒必要添加,因為Movie做為一個電影對象,Movie里的getPrice()就能取到Price實現類的價格.而現在不加Movie接口,就已經可以遵循開閉原則.至于要把Price抽象搞成接口,其實是這樣的,我想用抽象的原因是可以將抽象方法getCharge()改為方法(不抽象),這樣就會有默認的getCharge()實現.其實要是用接口也可以,但還要加入一個adapter.  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-16 09:19 曲靜波

          @黑蝙蝠
          新增類型只要加入新的類就行呀,不用修改以前的.若有配置文件,新增個配置就OK啦.  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-16 09:50 haojz

          這個例子說的不錯,
          想想上一個朋友說用配置文件, 的確更簡單,

          把影片的種類, 價格和策略用配置文件來描述,這樣維護和更新就更方便,
          不用添加新類;  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-16 16:27 bean

          這個確實是state模式嗎?
          我怎么感覺像是策略模式呢?
          沒有感覺和狀態機一樣,里面的狀態進行改變了阿?  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-16 19:36 曲靜波

          @bean
          老兄,這個我現在也不敢確認,我回頭查下資料,確定下來具體模式.  回復  更多評論   

          # re: 使用state pattern替代if else 2006-10-17 11:41 曲靜波

          十分對不起各位,這個實例確實應用的應屬Decorator pattern,標題我就不改了。以示警戒,感謝bean老兄。  回復  更多評論   

          # re: 使用decorator pattern替代if else 2006-10-18 15:25 123bingbing

          增開7群,號碼 30440732
          8群 30756649
          9群 30178567
          10群 28694497

          我們的qq群:15096318 學習程序的都可以來
            回復  更多評論   

          # re: 使用state pattern替代if else[未登錄] 2007-03-16 13:35 阿蜜果

          寫得不錯,受益了  回復  更多評論   

          # re: 使用state pattern替代if else[未登錄] 2007-10-29 09:25 timothy

          不錯,值得學習。如果業務被確定為有大量的擴展,可以考慮使用state pattern將系統進行重構,但我比較傾向于不要一開始就大量使用模式  回復  更多評論   

          # re: 使用state pattern替代if else 2008-05-06 16:27 fanlei

          支持小曲老師。  回復  更多評論   

          # re: 使用state pattern替代if else 2013-05-25 10:53 jehovah0121

          請教為什么這不是策略模式而是狀態模式?@曲靜波
            回復  更多評論   


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          統計

          常用鏈接

          留言簿(3)

          隨筆分類(9)

          隨筆檔案(8)

          文章分類

          友情鏈接

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 乌苏市| 渝中区| 婺源县| 涡阳县| 临泽县| 五家渠市| 湖州市| 修文县| 克拉玛依市| 西贡区| 拉孜县| 靖西县| 新营市| 汨罗市| 鄂托克前旗| 桦川县| 剑川县| 盐城市| 嵩明县| 凤阳县| 彝良县| 民权县| 武清区| 瑞丽市| 海淀区| 临湘市| 黄平县| 河曲县| 宁化县| 华坪县| 大厂| 白水县| 克拉玛依市| 和田县| 玉门市| 开封县| 泰来县| 房产| 沙湾县| 南丰县| 乌拉特中旗|