2020最新馬士兵Java架構師vip課程百度雲---代理模式與裝飾器模式的區別
代理模式和裝飾器模式非常相近,本文通過舉例,針對倆者的區別進行探討。
示例:孩子會吃飯
public interface IChild {
void eat();
}
建立孩子類,實現吃飯介面:
public class Child implements IChild{
@Override
public void eat() {
Log.e("TAG","孩子吃飯");
}
}
如果孩子太小,不會做飯,連吃飯都需要引導,這時候就需要一個代理幫助孩子正確處理吃飯流程:
建立父母(代理)類:
public class Parent implements IChild{ private Child child; private Parent(Child child){ this.child = child; } @Override public void eat() { Log.e("TAG","父母做飯"); child.eat(); Log.e("TAG","父母收拾餐具"); } }
其中有些孩子長大了,學會了自己做飯、自己吃飯,生活獨立自主:
建立孩子擴充套件(裝飾)類:
public class ChildWrapper implements IChild{ private Child child; public ChildWrapper(Child child){ this.child = child; } @Override public void eat() { Log.e("TAG","孩子做飯"); child.eat(); Log.e("TAG","孩子收拾餐具"); } }
以上是代理和裝飾的簡化寫法,如果不探究其表達的意義,倆者是沒有區別的。
但是從實際意義出發,就可以看出倆者的區別:
代理,偏重因自己無法完成或自己無需關心,需要他人干涉事件流程,更多的是對物件的控制。
裝飾,偏重對原物件功能的擴充套件,擴充套件後的物件仍是是物件本身。
這樣說有些抽象,繼續接著上例:
孩子長大了,需要去上學讀書,新增學生介面:
public interface IStudent {
void readBook();
}
孩子多了一重身份--學生,故要實現學生介面:
public class Child implements IChild, IStudent { @Override public void eat() { Log.e("TAG", "孩子吃飯"); } @Override public void readBook() { Log.e("TAG", "孩子讀書"); } }
此時,上述部分獨立自主的孩子(裝飾類),因為身份的增加,也要相應的擴充套件:
public class ChildWrapper implements IChild, IStudent {
private Child child;
public ChildWrapper(Child child) {
this.child = child;
}
@Override
public void eat() {
Log.e("TAG", "孩子做飯");
child.eat();
Log.e("TAG", "孩子收拾餐具");
}
@Override
public void readBook() {
child.readBook();
}
}
孩子成為了學生,但讀書不是宅家裡自學這麼簡單,需要有人教學,這顯然不是父母的任務,而是學校的事情。於是新增學校代理:
public class School implements IStudent {
private ArrayList<IStudent> students;
public void addStudent(IStudent student) {
students.add(student);
}
@Override
public void readBook() {
for (IStudent student : students) {
student.readBook();
}
}
}
學校招收學生入學,獨立自主的孩子作為裝飾類,本質還是孩子,肩負學生這一身份,可以作為學生入學,而原先的父母作為代理類不能入學:
Child child = new Child();
ChildWrapper wrapper = new ChildWrapper(child);
Parent parent = new Parent(child);
School school = new School();
school.addStudent(wrapper);
通過上述例子,相信可以直觀的看出:
孩子有吃飯和學習倆件任務,父母作為代理類之一,只能指導吃飯;學校作為代理類之一,只能指導學習。
對於某些獨立自主的孩子(裝飾類),它可能學習更加主動,吃完飯會主動收拾碗筷,但這些本來就是它原有功能的加強,它的本質仍然是孩子,依然可以享受父母、學校的代理幫助。
所以:
代理模式,注重對物件某一功能的流程把控和輔助。它可以控制物件做某些事,重心是為了借用物件的功能完成某一流程,而非物件功能如何。
裝飾模式,注重對物件功能的擴充套件,它不關心外界如何呼叫,只注重對物件功能的加強,裝飾後還是物件本身。
對於代理類,如何呼叫物件的某一功能是思考重點,而不需要兼顧物件的所有功能;
對於裝飾類,如何擴充套件物件的某一功能是思考重點,同時也需要兼顧物件的其它功能,因為再怎麼裝飾,本質也是物件本身,要擔負起物件應有的職責。
從上述例子也可以看出:
被裝飾者一旦身份增加,作為裝飾類,也需要相應的擴充套件,這必然造成編碼的負擔。
設計模式本身是為了提升程式碼的可擴充套件性,靈活運用即可,不必生搬硬套,非要分出個所以然來,裝飾器模式和代理模式的區別即是如此。