設(shè)計(jì)模式七大原則

設(shè)計(jì)模式七大原則

設(shè)計(jì)模式體現(xiàn)了代碼的耦合性佛析, 內(nèi)聚性以及可維護(hù)性彪蓬,可擴(kuò)展性捺萌,重用性桃纯,靈活性。

  • 1盐数、代碼重用性(即:相同功能的代碼伞梯,不用多次編寫)
  • 2、可讀性(即:編程規(guī)范性漾峡,便于其他程序員的閱讀和理解)
  • 3喻旷、可擴(kuò)展性(即:當(dāng)需要增加新的功能時,非常的方便槽袄,稱為可維護(hù))
  • 4锋谐、可靠性(即:當(dāng)我們增加新的功能后涮拗,對原來的功能沒有影響)
  • 5合搅、使程序呈現(xiàn)高內(nèi)聚歧蕉,低耦合的特性

一、單一職責(zé)原則(Single responsibility)

單一職責(zé)原則注意事項(xiàng)和細(xì)節(jié):

  • 1惯退、降低類的復(fù)雜度,一個類只負(fù)責(zé)一項(xiàng)職責(zé)锁蠕;
  • 2懊蒸、提高類的可讀性,可維護(hù)性骑丸;
  • 3、降低變更引起的風(fēng)險;
  • 4通危、通常情況下,應(yīng)當(dāng)遵守單一職責(zé)原則菊碟, 只有邏輯足夠簡單,才可以在方法級違反單一職責(zé)原則逆害。
/**
 * @author Yu
 * 只有類中方法數(shù)量足夠少头镊,可以在方法級別保持單一職責(zé)原則
 */
public class SingleResponsility {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();
        vehicle.run("布加迪威龍");
        vehicle.fly("波音747");
    }
}

// 邏輯簡單魄幕,方法級別實(shí)現(xiàn)單一職責(zé)
// 邏輯復(fù)雜拧晕,分類實(shí)現(xiàn)單一職責(zé)
class Vehicle {

    public void run(String string) {
        System.out.println(string + ":是陸地交通工具");
    }

    public void fly(String string) {
        System.out.println(string + ":是空中交通工具");
    }
}

二梅垄、接口隔離原則(Interface Segregation)

  • 1、類A通過接口 Interface1队丝、2 依賴類B靡馁,類C通過接口 Interface1机久、3 依賴類D,如果接口 Interface 對于 類A 和 類C 來說不是最小接口胧弛,那么 類B 和 類D 必須去實(shí)現(xiàn)他們不需要的方法。
  • 2损晤、將接口 Interface 拆分為獨(dú)立的幾個接口,類A 和 類C 分別與他們需要的接口建立依賴關(guān)系尤勋。也就是采用接口隔離原則最冰。
  • 3稀火、接口 Interface 中出現(xiàn)的方法,根據(jù)實(shí)際情祝拆分為三個接口篇裁。
image
public class InterfaceSegregation {
    public static void main(String[] args) {
        A a = new A();
        a.depend1(new B());
        a.depend2(new B());
        a.depend3(new B());

        C c = new C();
        c.depend1(new D());
        c.depend4(new D());
        c.depend5(new D());
    }
}

interface interface1 {
    void Operation1();
}

interface interface2 {
    void Operation2();

    void Operation3();
}

interface interface3 {
    void Operation4();

    void Operation5();
}

class B implements interface1, interface2 {

    @Override
    public void Operation1() {
        System.out.println("B 實(shí)現(xiàn)了 Operation1");
    }

    @Override
    public void Operation2() {
        System.out.println("B 實(shí)現(xiàn)了 Operation2");
    }

    @Override
    public void Operation3() {
        System.out.println("B 實(shí)現(xiàn)了 Operation3");
    }
}

class D implements interface1, interface3 {

    @Override
    public void Operation1() {
        System.out.println("D 實(shí)現(xiàn)了 Operation1");
    }

    @Override
    public void Operation4() {
        System.out.println("D 實(shí)現(xiàn)了 Operation4");
    }

    @Override
    public void Operation5() {
        System.out.println("D 實(shí)現(xiàn)了 Operation5");
    }
}

class A {

    public void depend1(interface1 i) {
        i.Operation1();
    }

    public void depend2(interface2 i) {
        i.Operation2();
    }

    public void depend3(interface2 i) {
        i.Operation3();
    }
}

class C {

    public void depend1(interface1 i) {
        i.Operation1();
    }

    public void depend4(interface3 i) {
        i.Operation4();
    }

    public void depend5(interface3 i) {
        i.Operation5();
    }
}

三、依賴倒轉(zhuǎn)原則(Dependence Inversion)

  • 1、高層模塊不應(yīng)該依賴低層模塊粉渠,二者都應(yīng)該依賴其抽象(緩沖層)霸株;
  • 2去件、抽象不應(yīng)該依賴細(xì)節(jié)尤溜,細(xì)節(jié)應(yīng)該依賴抽象汗唱;
  • 3哩罪、依賴倒轉(zhuǎn)(倒置)的中心思想是面向接口編程;
  • 4巡验、依賴倒轉(zhuǎn)原則是基于這樣的設(shè)計(jì)理念:相對于細(xì)節(jié)的多變性碘耳,抽象的東西要穩(wěn)定的多显设。以抽象為基礎(chǔ)搭建的架構(gòu)比以細(xì)節(jié)為基礎(chǔ)的架構(gòu)要穩(wěn)定的多。在java中绞蹦, 抽象指的是接口或抽象類,細(xì)節(jié)就是具體的實(shí)現(xiàn)類澡屡;
  • 5驶鹉、使用接口或抽象類的目的是制定好規(guī)范,而不涉及任何具體的操作徙缴,把展現(xiàn)細(xì)節(jié)的任務(wù)交給他們的實(shí)現(xiàn)類去完成。

依賴關(guān)系三種傳遞方式:

  • 接口傳遞(依賴)
  • 構(gòu)造方法傳遞(依賴)
  • setter方式傳遞(聚合)
public class DependenceInversion {
    public static void main(String[] args) {
        Person person = new Person();
        person.receive(new Email());
        person.receive(new WeChat());
    }
}

interface Info{
    String getInfo();
}

class Email implements Info{

    @Override
    public String getInfo() {
        return "Receive Email";
    }
}

class WeChat implements Info{

    @Override
    public String getInfo() {
        return "Receive WeChat";
    }
}

//person 接受信息
class Person {

    public void receive(Info info) {
        System.out.println(info.getInfo());
    }
}

四、里氏替換原則(Liskov Substitution)

  • 1、里氏替換原則(Liskov Substitution Principle)在1988年,由麻省理工學(xué)院一位姓里的女士提出絮蒿;
  • 2、如果對每個類型為T1的對象o1常侣,都有類型為T2的對象o2胳施,使得以T1定義的所有程序P在所有的對象o1都代換成o2時舞肆,程序P的行為沒有發(fā)生變化椿胯,那么類型T2是類型T1的子類型种冬。換句話說镣丑,所有引用基類的地方必須能透明地使用其子類的對象舔糖;
  • 3娱两、在使用繼承時,遵循里氏替換原則金吗,在子類中盡量不要重寫父類的方法十兢;
  • 4、繼承實(shí)際上讓兩個類耦合性增強(qiáng)了摇庙,給程序帶來侵入性旱物。在適當(dāng)?shù)那闆r下,可以通過聚合卫袒,組合宵呛,依賴來解決問題;
  • 5夕凝、繼承包含這樣一層含義:父類中凡是已經(jīng)實(shí)現(xiàn)好的方法宝穗,實(shí)際上是在設(shè)定規(guī)范和契約户秤,雖然它不強(qiáng)制要求所有的子類必須遵循這些契約,但是如果子類對這些已經(jīng)實(shí)現(xiàn)的方法任意修改逮矛,就會對整個繼承體系造成破壞鸡号。
public class LiskovSubstitution {
    public static void main(String[] args) {
        A a = new A();
        System.out.println("2-1=" + a.func1(2, 1));

        B b = new B();
        System.out.println("2+1=" + b.func1(2, 1));
        System.out.println("2+1+9=" + b.func2(2, 1));
        System.out.println("B類使用A類方法:2-1=" + b.func3(2, 1));
    }
}

class Base {
    //把基礎(chǔ)方法和成員抽取成基類
    public int func1(int num1, int num2) {
        return num1 - num2;
    }
}

class A extends Base {

//    public int func1(int num1, int num2) {
//        return num1 - num2;
//    }
}

class B extends Base {

      // TODO 類 B `無意` 重寫了父類 A 方法,造成原有方法發(fā)生改變须鼎。
//    @Override
//    public int func1(int num1, int num2) {
//        return num1 + num2;
//    }

    @Override
    public int func1(int num1, int num2) {
        return num1 + num2;
    }

    public int func2(int num1, int num2) {
        return func1(num1, num2) + 9;
    }

    private A a = new A();//組合

    //使用 A 方法
    public int func3(int num1, int num2) {
        return this.a.func1(num1, num2);
    }
}

五鲸伴、開閉原則 OCP(Open Closed)

  • 1、開閉原則(Open Closed Principle) 是編程中最基礎(chǔ)晋控、最重要的設(shè)計(jì)原則汞窗;
  • 2、一個軟件實(shí)體糖荒,比如類杉辙,模塊和函數(shù)應(yīng)該對提供方擴(kuò)展開放,對使用方修改關(guān)閉捶朵。用抽象構(gòu)建框架蜘矢,用實(shí)現(xiàn)擴(kuò)展細(xì)節(jié);
  • 3综看、當(dāng)軟件需要變化時品腹,盡量通過擴(kuò)展軟件實(shí)體的行為來實(shí)現(xiàn)變化,而不是通過修改已有的代碼來實(shí)現(xiàn)變化红碑;
  • 4舞吭、編程中遵循其它原則,以及使用設(shè)計(jì)模式的目的就是遵循開閉原則析珊。
public class OpenClosed {
    public static void main(String[] args) {
        Use use = new Use();
        use.drawShape(new Triangle());
        use.drawShape(new Circle());
        use.drawShape(new OtherGraphics());//只需要讓 此類繼承 抽象類羡鸥,子類實(shí)現(xiàn)具體方法  OCP原則
    }
}

class Use {
    public void drawShape(Shape shape) {
        shape.draw();
    }
}

abstract class Shape {
    public abstract void draw();
}

class Triangle extends Shape {

    @Override
    public void draw() {
        System.out.println("子類實(shí)現(xiàn)具體功能:三角形");
    }
}

class Circle extends Shape {

    @Override
    public void draw() {
        System.out.println("子類實(shí)現(xiàn)具體功能:圓形");
    }
}

class OtherGraphics extends Shape {

    @Override
    public void draw() {
        System.out.println("子類實(shí)現(xiàn)具體功能:任何形狀");
    }
}

六、迪米特法則(Demeter)

  • 1忠寻、一個對象應(yīng)該對其他對象保持最少的了解(最少知道原則 LKP)惧浴。
  • 2、類與類關(guān)系越密切奕剃,耦合度越大衷旅。要求降低類之間耦合,而不是完全解耦纵朋。
  • 3柿顶、迪米特法則(Demeter Principle),即一個類對自己依賴的類知道的越少越好操软。也就是說嘁锯,對于被依賴的類不管多么復(fù)雜,都盡量將邏輯封裝在類的內(nèi)部。對外除了提供public方法家乘,不對外泄露任何信息品山。
  • 4、迪米特法則更簡單的定義:只與直接的朋友通信烤低。
  • 5肘交、直接的朋友:每個對象都會與其他對象有耦合關(guān)系,只要兩個對象之間有耦合關(guān)系扑馁,我們就說這兩個對象之間是朋友關(guān)系涯呻。耦合的方式很多,依賴腻要,關(guān)聯(lián)复罐,組合,聚合 等雄家。其中效诅,我們稱出現(xiàn)成員變量,方法參數(shù)趟济,方法返回值中的類為直接的朋友乱投,而出現(xiàn)在局部變量中的類不是直接的朋友。也就是說顷编,陌生的類最好不要以局部變量的形式出現(xiàn)在類的內(nèi)部戚炫。
class A{
    B b;//全局變量 - 直接朋友
    public B m1(){} //方法返回值 - 直接朋友
    public void m2(B b){}//方法入?yún)?- 直接朋友
    public void m3(){
        B b1 = new B();// 局部變量 非直接朋友
    }
}
public class Demeter {
    public static void main(String[] args) {
        SchoolManager schoolManager = new SchoolManager();
        schoolManager.printAllEmployee(new CollegeManager());
    }
}

//學(xué)院員工類
class CollegeEmployee {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

//管理學(xué)院員工的管理類:
class CollegeManager {
    //返回學(xué)院的所有員工 //TODO CollegeEmployee 直接朋友
    public List<CollegeEmployee> getAllEmployee() {
        List<CollegeEmployee> list = new ArrayList<CollegeEmployee>();
        for (int i = 0; i < 10; i++) { //這里我們增加了10 個員工到list ,
            CollegeEmployee emp = new CollegeEmployee();
            emp.setId("學(xué)院員工id " + i);
            list.add(emp);
        }
        return list;
    }

    public void printCollegeEmployee() {
        List<CollegeEmployee> list1 = this.getAllEmployee();
        System.out.println("---學(xué)院員工----");
        for (CollegeEmployee e : list1) {
            System.out.println(e.getId());
        }
    }
}

//學(xué)邢蔽常總部員工類
class SchoolEmployee {
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

//學(xué)校管理類
//TODO 直接朋友 Employee CollegeManager
class SchoolManager {
    //返回學(xué)兴簦總部的員工
    public List<SchoolEmployee> getAllEmployee() {
        List<SchoolEmployee> list = new ArrayList<SchoolEmployee>();
        for (int i = 0; i < 5; i++) { //這里我們增加了5個員工到list
            SchoolEmployee emp = new SchoolEmployee();
            emp.setId("學(xué)校總部員工id= " + i);
            list.add(emp);
        }
        return list;
    }

    //該方法完成輸出學(xué)信セ荩總部和學(xué)院員工信息(id)
    void printAllEmployee(CollegeManager sub) {
        //獲取到學(xué)院員工
        //TODO 非直接朋友 CollegeEmployee  應(yīng)該提取到  CollegeManager
//        List<CollegeEmployee> list1 = sub.getAllEmployee();
//        System.out.println("---學(xué)院員工----");
//        for (CollegeEmployee e : list1) {
//            System.out.println(e.getId());
//        }
        sub.printCollegeEmployee();//只提供方法茅糜,不把具體實(shí)現(xiàn)放在其他類里面。

        //獲取到學(xué)兴赝欤總部員工
        List<SchoolEmployee> list2 = this.getAllEmployee();
        System.out.println("------學(xué)忻镒福總部員工------");
        for (SchoolEmployee e : list2) {
            System.out.println(e.getId());
        }
    }
}

七、合成復(fù)用原則(Composite Reuse)

合成復(fù)用原則 盡量使用組合/聚合的方式毁菱,而不是使用繼承米死。

  • 1锌历、找出應(yīng)用中可能需要變化之處贮庞,把它們獨(dú)立出來,不要和那些不需要變化的代碼混在一起究西。
  • 2窗慎、針對接口編程,而不是針對實(shí)現(xiàn)編程。
  • 3遮斥、為了交互對象之間的松耦合設(shè)計(jì)而努力峦失。
public class CompositeReuse {
    public static void main(String[] args) {
        System.out.println("------依賴------");
        B b = new B();
        b.Operation1(new A());

        System.out.println("------聚合------");
        b.setA(new A());
        b.Operation2();

        System.out.println("------組合------");
        b.Operation3();
    }
}

class A {
    void Operation1() {
        System.out.println("A Operation1");
    }

    void Operation2() {
        System.out.println("A Operation2");
    }

    void Operation3() {
        System.out.println("A Operation3");
    }
}

//如果只是需要用到 A類的方法,盡量不要使用繼承术吗。而是使用尉辑,依賴,聚合较屿,組合的方式
class B {
    void Operation1(A a) {//TODO 依賴
        a.Operation1();
        a.Operation2();
        a.Operation3();
    }

    //==============================================================
    A a;
    public void setA(A a) {
        this.a = a;
    }

    void Operation2() {//TODO 聚合
        a.Operation1();
        a.Operation2();
        a.Operation3();
    }

    //==============================================================
    A a1 = new A();

    void Operation3() {//TODO 組合
        a1.Operation1();
        a1.Operation2();
        a1.Operation3();
    }
}

八: UML(Unified Modeling Language)

IDEA PlantUML表示類與類之間的關(guān)系的符號

@startuml

Class1 <|-- ClassA:泛化
Class2 <-- ClassB:關(guān)聯(lián)
Class3 *-- ClassC:組合
Class4 o-- ClassD:聚合
Class5 <|.. ClassE:實(shí)現(xiàn)
Class6 <.. ClassF:依賴

@enduml
image
8.1: 依賴(Dependence)

只要是在類中用到了對方隧魄,那么他們之間就存在依賴關(guān)系。如果沒有對方隘蝎,連編繹都通過不了购啄。

  • 類中用到了對方;
  • 類的成員屬性嘱么;
  • 方法的返回類型狮含;
  • 方法接收的參數(shù)類型;
  • 方法中使用到曼振。
image
/**
 * @author Yu
 * 類中用到了對方几迄;
 * 類的成員屬性;
 * 方法的返回類型冰评;
 * 方法接收的參數(shù)類型乓旗;
 * 方法中使用到;
 */
public class Dependence {
    A a;//TODO 類的成員屬性

    public A save(B b) {//TODO 方法接收的參數(shù)類型
        //TODO 方法的返回類型
        System.out.println("");
        A a = new A();//TODO 方法中使用到
        return a;
    }
}

class A {}

class B {}
8.2: 繼承(泛化 Generalization)

泛化關(guān)系實(shí)際上就是繼承關(guān)系集索,依賴關(guān)系的特例屿愚。

image
public class Generalization extends Base {

    @Override
    public void get(Object oId) {

    }

    @Override
    public void put(Object oName) {

    }
}

abstract class Base {
    abstract public void get(Object oId);

    abstract public void put(Object oName);
}
8.3: 實(shí)現(xiàn)(Realization)

實(shí)現(xiàn)關(guān)系實(shí)際上就是 A類 實(shí)現(xiàn) B接口,依賴關(guān)系的特例务荆。

image
public class Implementation implements Base {
    @Override
    public void init() {
        System.out.println("init");
    }
}

interface Base {
    void init();
}
8.3: 關(guān)聯(lián)(Association)

類與類之間的關(guān)系妆距,依賴關(guān)系的特例。

關(guān)聯(lián)具有導(dǎo)航性:即雙向關(guān)系或單向關(guān)系函匕。

image
public class Person {
    private IDCard idCard;
}

class IDCard {
    //private Person person;
}
8.4: 聚合(Aggregation)

表示的是整體和部分的關(guān)系娱据,整體與部分可以分開,關(guān)聯(lián)關(guān)系的特例盅惜。

聚合關(guān)系是關(guān)聯(lián)關(guān)系的特例中剩,所以他具有關(guān)聯(lián)的導(dǎo)航性與多重性。

image
public class Computer {
    private Mouse mouse;
    private Keyboard keyboard;

    public void setMouse(Mouse mouse) {
        this.mouse = mouse;
    }

    public void setKeyboard(Keyboard keyboard) {
        this.keyboard = keyboard;
    }
}

class Mouse {}

class Keyboard {}

組合(Composite)

整體與部分的關(guān)系抒寂,但是整體與部分不可以分開结啼,關(guān)聯(lián)關(guān)系的特例。

級聯(lián)刪除就是組合關(guān)系屈芜。

image
public class Computer {
   private CPU cpu = new CPU();
   private SSD ssd = new SSD();
}

class CPU {}

class SSD {}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末郊愧,一起剝皮案震驚了整個濱河市朴译,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌属铁,老刑警劉巖眠寿,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異焦蘑,居然都是意外死亡盯拱,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門例嘱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坟乾,“玉大人,你說我怎么就攤上這事蝶防∩趼拢” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵间学,是天一觀的道長殷费。 經(jīng)常有香客問我,道長低葫,這世上最難降的妖魔是什么详羡? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮嘿悬,結(jié)果婚禮上实柠,老公的妹妹穿的比我還像新娘。我一直安慰自己善涨,他們只是感情好窒盐,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著钢拧,像睡著了一般蟹漓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上源内,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天葡粒,我揣著相機(jī)與錄音,去河邊找鬼膜钓。 笑死嗽交,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的颂斜。 我是一名探鬼主播夫壁,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼焚鲜!你這毒婦竟也來了掌唾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤忿磅,失蹤者是張志新(化名)和其女友劉穎糯彬,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葱她,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撩扒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吨些。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搓谆。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖豪墅,靈堂內(nèi)的尸體忽然破棺而出泉手,到底是詐尸還是另有隱情,我是刑警寧澤偶器,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布斩萌,位于F島的核電站,受9級特大地震影響屏轰,放射性物質(zhì)發(fā)生泄漏颊郎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一霎苗、第九天 我趴在偏房一處隱蔽的房頂上張望姆吭。 院中可真熱鬧,春花似錦唁盏、人聲如沸内狸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽答倡。三九已至,卻和暖如春驴党,著一層夾襖步出監(jiān)牢的瞬間瘪撇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工港庄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留倔既,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓鹏氧,卻偏偏與公主長得像渤涌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子把还,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

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