設計模式———裝飾模式
例子:成績單報告
在面向對象的設計中,如果超過兩層繼承,可能就出設計問題了。這是經驗總結,并非定論。繼承層次越多,維護成本越多。

成績裝飾模型
增加一個抽象類和兩個實現(xiàn)類,其中Decorator的作用是封裝SchoolReort類
抽象成績單
//抽象成績單
public abstract class SchoolReport{
public abstract void report();
public abstract void sign(String name);
}
具體的四年級成績
public abstract FourthGradeSchoolReport extends SchoolReport{
public void report(){
System.out.println("尊敬的XX家長");
System.out.println("成績如下");
System.out.println("語文xx");
// ...
}
public void sign(String name){
System.out.println("家長簽名為:"+name);
}
}
修飾的抽象類
// 修飾的抽象類
public abstract class Decorator extends SchoolReport{
private SchoolReport sr;
public Decorator(SchoolReport sr){
this.sr = sr;
}
// 報告成績
public void report(){
this.sr.report();
}
//家長簽名
public void sign(String name){
this.sr.sign(name);
}
}
最高成績修飾
public class HighScoreDecorator extends Decorator {
public HighScoreDecorator(SchoolReport sr){
super(sr);
}
private void reportHighScore(){
System.out.println("最高成績是:XX");
}
public void report(){
this.reportHighScore();
super.report();
}
}
排名情況修飾
public class SortDecorator extends Decorator {
public SortDecorator(SchoolReport sr){
super(sr);
}
public void reportSort(){
System.out.println("排名情況是xx");
}
@Override
public void report(){
this.reportSort();
super.report();
}
}
查看成績單
public class Father{
public static void main(String[] args) {
//把成績單拿過來
SchoolReport sr;
//原裝的成績單
sr = new FourthGradeSchoolReport();
//加了最高分說明的成績單
sr = new HighScoreDecorator(sr);
// 加了排名的說明
sr = new SortDecorator(sr);
//看成績單
sr.report();
sr.sign("name");
}
}
裝飾模式的定義
Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.
動態(tài)地給一個對象添加一些額外的職責。就增加功能來說,裝飾模式相比生成子類更為靈活。

裝飾模式
四個角色說明
- component抽象構件
- component是一個接口或者是抽象類,就是定義我們最核心的對象,也就是最原始的對象
- 在裝飾模式中,必然有一個最基本,最核心,也就是最原始的對象
- concreteComponent具體構建
- concreteComponent是最核心,最原始,最基本的接口或抽象類的實現(xiàn),要裝飾的就是它
- Decorator裝飾角色
- 一般是一個抽象類,實現(xiàn)接口或者抽象方法
- 它的屬性里必定有一個private變量指向Component抽象構建
- ConcreteDecorator具體裝飾角色
- ConcreteDecoratorA和ConcreteDecoratorB是兩個具體的裝飾類,要把最原始,最基本,最核心的進行裝飾
抽象構件
public abstract class Component{
//抽象的方法
public abstract void operate();
}
具體構件
public class ConcreteComponent extends Component {
// 具體實現(xiàn)
public void operate(){
// code to do something
System.out.println("doSomethin");
}
}
抽象裝飾者
public abstract class Decorator extends Component{
//必然有一個變量是抽象構件
private Component component = null;
//通過構造函數傳遞被修飾者
public Decorator(Component component){
this.component = component;
}
//委托給被修飾者執(zhí)行
@Override
public void operate(){
this.component.operate();
}
}
具體的裝飾類
public class ConcreteDecorator1 extends Decorator{
public ConcreteDecorator1(Component component){
super(component);
}
//定義自己的修飾方法
public void method(){
//code to do something
}
public void operate(){
this.method();
super.operate();
}
}
public class ConcreteDecorator2 extends Decorator{
public ConcreteDecorator2(Component component){
super(component);
}
//定義自己的修飾方法
public void method(){
//code to do something
}
public void operate(){
this.method();
super.operate();
}
}
場景類
public class Client{
public static void main(String[] args) {
Component component = new ConcreteComponent();
// 第一次修飾
component = new ConcreteDecorator1(component);
// 第二次修飾
component = new ConcreteDecorator2(component);
//運行結果
component.operate();
}
}
裝飾模式的優(yōu)缺點
裝飾模式的優(yōu)點
- 裝飾類和被裝飾類可以獨立發(fā)展,不會相互耦合。
- Component類無需知道Decorator類,Decorator類是從外部來擴展Component類的功能,Decorator也不用知道具體的構件
- 裝飾模式是繼承關系的一個替代方案
- 裝飾類Decorator不管裝飾多少層,返回的對象還是Component,實現(xiàn)的還是is-a關系
- 裝飾模式可以動態(tài)地擴展一個實現(xiàn)類的功能,這不需要多說,裝飾模式的定義就是如此
裝飾模式的缺點
- 多層的裝飾是比較復雜的
- 盡量減少裝飾類的數量,一遍降低系統(tǒng)的復雜度
裝飾模式的使用場景
- 需要擴展一個類的功能,或給出一個類增加附加功能
- 需要動態(tài)地給一個對象增加功能,這些功能可以再動態(tài)地撤銷
- 需要為一批的兄弟類進行改裝或加裝功能,當然是首選裝飾模式