装饰者模式

it2022-05-05  69

装饰者模式,在不改变一个对象本身功能的基础上给对象增加额外的新行为。比如,我们到书店买书,在不改变书籍本身的基础上,赠送个书签,或者要个包装袋

 

装饰者模式(Decorator Pattern):在不改变原有对象的基础上,动态的给对象增加一些额外的职责。就给对象增加功能来说,装饰者模式比继承的方式更加灵活。装饰者模式是一种对象结构型模式

装饰者模式,无须定义子类动态给对象增加职责,用对象之间的关联关系取代类之间的继承关系

 

装饰者模式结构,需要4个角色,抽象构件、具体构件、抽象装饰类、具体装饰类

抽象构件(Component):具体构件和抽象装饰类的共同父类,声明了具体构件中实现的业务方法

具体构件(ConcreteComponent):抽象构件类的子类,定义具体构件对象

抽象装饰类(Decorator):抽象构件类的子类,作用是给具体构件增加功能,具体功能在其子类中实现

具体装饰类(ConcreteDecorator):抽象装饰类的子类,给构件添加新的功能

 

下面还是以买书为例,讲解装饰者模式

去书店买书,增加书签不要钱,增加一个书的包装袋,需额外加钱

定义抽象书籍类,在这里相当于抽象构件

package com.design.structural.decorator; /** * 抽象书籍类 */ public abstract class AbstractBook { //书名 public abstract void bookName(); //价格 public abstract void bookPrice(); }

定义具体书籍红楼梦,售价60元,相当于具体构件

package com.design.structural.decorator; public class TheDreamofRedMansionBook extends AbstractBook{ @Override public void bookName() { System.out.println("红楼梦"); } @Override public void bookPrice() { System.out.println("售价60元"); } }

定义抽象书籍装饰类,相当于抽象装饰类

package com.design.structural.decorator; public class AbstractDecorator extends AbstractBook{ private AbstractBook abstractBook; public AbstractDecorator(AbstractBook abstractBook){ this.abstractBook = abstractBook; } @Override public void bookName() { this.abstractBook.bookName(); } @Override public void bookPrice() { this.abstractBook.bookPrice(); } }

定义书签装饰类,相当于具体装饰类

package com.design.structural.decorator; /** * 书签装饰类 */ public class BookmarkDecorator extends AbstractDecorator{ public BookmarkDecorator(AbstractBook abstractBook) { super(abstractBook); } @Override public void bookName() { super.bookName(); System.out.println("增加一个书签"); } @Override public void bookPrice() { super.bookPrice(); } }

定义包装袋装饰类,相当于具体装饰类

package com.design.structural.decorator; /** * 包装袋装饰 */ public class PackDecorator extends AbstractDecorator{ public PackDecorator(AbstractBook abstractBook) { super(abstractBook); } @Override public void bookName() { super.bookName(); System.out.println("增加一个包装袋"); } @Override public void bookPrice() { super.bookPrice(); System.out.println("增加2元钱"); } }

 

类图如下

 

测试调用

不要书签和包装袋

package com.design.structural.decorator; public class TestMain { public static void main(String[] args) { AbstractBook abstractBook = new TheDreamofRedMansionBook(); //abstractBook = new BookmarkDecorator(abstractBook); //abstractBook = new PackDecorator(abstractBook); abstractBook.bookName(); abstractBook.bookPrice(); } }

要书签和包装袋

package com.design.structural.decorator; public class TestMain { public static void main(String[] args) { AbstractBook abstractBook = new TheDreamofRedMansionBook(); abstractBook = new BookmarkDecorator(abstractBook); abstractBook = new PackDecorator(abstractBook); abstractBook.bookName(); abstractBook.bookPrice(); } }

 

 

扩展

透明装饰者模式与半透明装饰者模式

透明装饰者模式(Transparent):标准的装饰者模式就是透明装饰者模式。透明装饰者模式要求客户端完全针对抽象编程,且对象全部声明为抽象构件类型。可以对一个已装饰过的对象进行多次装饰,得到更为复杂、功能更强大的对象。实现透明装饰者模式时,需要具体装饰类的方法覆盖抽象装饰类的方法,比如上边代码中的 bookName() 方法和 bookPrice() 方法,除此之外,还可以调用其他方法,增加新的功能

 

半透明装饰者模式(Semi-Transparent):用具体装饰类型来定义装饰之后的对象,用抽象构件类型来定义具体构件类型。即相对于客户端来说,具体构件类型无须关心,是透明的,但具体装饰类型必须指定,它是不透明的

请看下边代码,示例半透明装饰者模式

抽象书籍装饰类,相当于抽象装饰类

package com.design.structural.decorator; public class AbstractDecorator extends AbstractBook{ private AbstractBook abstractBook; public AbstractDecorator(AbstractBook abstractBook){ this.abstractBook = abstractBook; } @Override public void bookName() { this.abstractBook.bookName(); } @Override public void bookPrice() { this.abstractBook.bookPrice(); } }

书签装饰类,相当于具体装饰类

package com.design.structural.decorator; /** * 书签装饰类 */ public class BookmarkDecorator extends AbstractDecorator{ public BookmarkDecorator(AbstractBook abstractBook) { super(abstractBook); } @Override public void bookName() { super.bookName(); System.out.println("增加一个书签"); } @Override public void bookPrice() { super.bookPrice(); } public void pencil(){ System.out.println("赠送一个铅笔"); } }

书签装饰类,即具体装饰类,自行增加了 pencil() 方法,这个方法在其父类抽象书籍装饰类中是没有的,因此是不透明的。这种方式更加灵活,设计相对简单,但最大的缺点是同一个对象不能多次装饰,且客户端需要有区别地对待装饰之前的对象和装饰之后的对象

 

 

装饰者模式总结

优点:继承的有力补充、比继承灵活;符合开闭原则;

缺点:增加更多的代码,增加程序复杂性;多次装饰的对象,较为复杂,不易调试

适用场景:扩展一个类,或给一个类添加职责;动态给对象添加功能;不能采用继承方式扩展系统或继承方式不利于扩展和维护系统时,采用装饰者模式

 

 

 

 


最新回复(0)