裝飾模式
裝飾模式的定義:動態地給一個對象添加額外的職責,就添加功能來說,裝飾模式比生成子類更加靈活。
這段話比較抽象,自己根據裝飾模式實踐了一下,有了一些小小的領悟分享一下。
我們最開始有一抽象類,比如說是人,它有兩個子類分別是學生和老師,並且有一些共有的屬性放在抽象類“人”中,有一些獨有的屬性放在各自的學生類和老師類中。並且有一個虛函數要學生和老師類來實現。
這模擬的是我們已經有一個生態系統了。
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()函數。