裝飾模式學習筆記

裝飾模式

裝飾模式的定義動態地給一個對象添加額外的職責,就添加功能來說,裝飾模式比生成子類更加靈活。

這段話比較抽象,自己根據裝飾模式實踐了一下,有了一些小小的領悟分享一下。

我們最開始有一抽象類,比如說是人,它有兩個子類分別是學生和老師,並且有一些共有的屬性放在抽象類“人”中,有一些獨有的屬性放在各自的學生類和老師類中。並且有一個虛函數要學生和老師類來實現。
這模擬的是我們已經有一個生態系統了。

Person類:

public abstract class Person{
    public String name = "";
    public int age  = 0;

    public abstract void show();
}

Student類:

public class Student extends Person {
    private int grade = 0;

    public Student(String name, int age, int grade) {
        this.name = name;
        this.age = age;
        this.grade = grade;
    }

    @Override
    public void show() {
        System.out.println("Student "+name+"'s age is "+age+" in grade "+grade);
    }
}

teacher類:

public class Teacher extends Person {
    public Teacher(String name, int age) {
        this.name = name;
        this.age  = age;
    }
    @Override
    public void show() {
        System.out.println("Teacher "+name+"'s age is "+age);
    }
}

現在我們需要向Person添加一個功能,給每個人穿衣服並且顯示每個人的穿着。

在Person類中添加一個虛函數,再在各個類中實現穿衣這個穿衣函數,但是這種方法即難以實現又違背了開閉原則,因爲會去更改每個類。

裝飾模式提供了一種很好的解決方案:
定義一個接口,我的理解是定義一個需要添加的功能的接口,比如此種情況,我們定義一個Dress接口:

public interface Dress {
    public void dressing();
}

然後先對這個接口編寫各種衣服的類,所以先抽象出來一個衣物類Finary,它實現了接口。Finary的構造函數很重要,它指定需要裝飾哪個對象的Dress接口

public class Finery implements Dress {
    private Dress dress = null;
    public Finery(Dress dress) {
        this.dress = dress;
    }
    @Override
    public void dressing() {
        if(null != dress) {
            dress.dressing();
            System.out.println("Dressing:");
        }
    }
}

然後創建各項衣物類Finary的子類比如Tshirt、suit、tie。。。類

public class TShirt extends Finery{
    public TShirt(Dress dress) {
        super(dress);
    }

    @Override
    public void dressing() {
        super.dressing();
        System.out.println("TShirt");
    }
}
public class WearSuit extends Finery {

    public WearSuit(Dress dress) {
        super(dress);
    }

    @Override
    public void dressing() {
        super.dressing();
        System.out.println("WearSuit");
    }
}
public class WearTie extends Finery{
    public WearTie(Dress dress) {
        super(dress);
    }

    @Override
    public void dressing() {
        super.dressing();
        System.out.println("WearTie");
    }
}

然後是Person針對接口編程,因爲每個人都需要穿衣服,並且都需要穿內衣……

public abstract class Person implements Dress{
    public String name = "";
    public int age  = 0;

    @Override
    public void dressing() {
        System.out.println("Dressing: UnderWear");
    }

    public abstract void show();
}

對於student和teacher類這裏不需要重寫dressing(),這是裝飾模式最重要的應用點!!!即不需要修改已經實例化的Person子類,只需要抽象類Person針對接口編程,符合開閉原則,完美啊!!!

最後來看下是怎麼調用的:

 public static void main(String[] args) {
        Person person = new Student("peter",15,2);
        person.show();
        Dress studentDress = person;
        studentDress = new TShirt(studentDress);
        studentDress = new BigTrousers(studentDress);
        studentDress.dressing();

        person = new Teacher("jobey",35);
        person.show();
        Dress teacherDress = person;
        teacherDress = new WearSuit(teacherDress);
        teacherDress = new WearTie(teacherDress);
        teacherDress.dressing();
    }

我們new一個student的時候,不僅實例化了一個學生對象,並且也實現了一個Dress接口,原來student的內容不需要改,要給每個學生穿衣服只需要將person的Dress接口提取出來:

Dress studentDress = person;

然後對person的Dress接口“穿衣服”就行了!!!
此處就是對實例化了的stduent的Dress接口studentDress進行“穿衣服”:

studentDress = new TShirt(studentDress);
studentDress = new BigTrousers(studentDress);
studentDress.dressing();

輸出結果:

Student peter's age is 15 in grade 2
Dressing: UnderWear
Dressing: TShirt
Dressing: BigTrousers
Teacher jobey's age is 35
Dressing: UnderWear
Dressing: WearSuit
Dressing: WearTie
studentDress.dressing();

首先調用的是Person實現的dressing(),我的理解是畢竟這是new person才創建的接口嘛,之後是按“穿衣”順序來調用dressing()函數。

發佈了27 篇原創文章 · 獲贊 2 · 訪問量 9669
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章