定义
装饰者模式又名包装模式。动态的给一个对象添加一些额外的职责。
装饰者模式适用场景:
(1)以动态的方式给对象添加职责。
(2)处理那些可以撤销的职责。
(3)当采用生成子类的方法进行扩充时,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。
装饰模式一共有四个角色。
(1)抽象组件(Component):给出一个抽象接口,以规范准备接受附加责任的对象。
(2)被装饰者(ConcreteComponent):Component的具体实现,也就是我们要装饰的具体对象。
(3)装饰者组件(Decorator):持有组件对象的实例引用,该类的职责就是为了装饰具体组件对象,定义的基类。
(4)具体装饰(ConcreteDecorator):负责给构件对象装饰附加的功能。
举个栗子
比如说我们去买蛋糕,蛋糕可以装饰成不同的水果蛋糕。
第一步:定义蛋糕接口(Component)
public interface Cake { // 蛋糕名字 String cakeName(); // 蛋糕价格 int cakePrice(); }
第二步:定义两种不同形状的蛋糕:圆形蛋糕和正方形蛋糕(ConcreteComponent)
public class CircleCake implements Cake { @Override public String cakeName() { return "圆形蛋糕"; } @Override public int cakePrice() { return 46; } } public class RectangleCake implements Cake { @Override public String cakeName() { return "正方形蛋糕"; } @Override public int cakePrice() { return 52; } }
第三步:定义蛋糕口味抽象类(Decorator)
public abstract class TasteDecorator implements Cake { // 具体蛋糕name由子类定义 @Override public abstract String cakeName(); // 具体蛋糕价格由子类定义 @Override public abstract int cakePrice(); }
第四步:具体蛋糕口味(ConcreteDecorator):加芒果和草莓
public class AddMangoTaste extends TasteDecorator { private String description = "蛋糕加芒果"; private Cake cake = null; public AddMangoTaste(Cake cake){ this.cake = cake; } // 为蛋糕加芒果 @Override public String cakeName() { return cake.cakeName() + " " + description; } // 价格增加10元 @Override public int cakePrice() { return cake.cakePrice() + 10; } } public class AddStrawberryTaste extends TasteDecorator{ private String description = "蛋糕加草莓"; private Cake cake = null; public AddStrawberryTaste(Cake cake){ this.cake = cake; } // 为蛋糕加草莓 @Override public String cakeName() { return cake.cakeName() + " " + description; } // 价格增加15元 @Override public int cakePrice() { return cake.cakePrice() + 15; } }
第五步:模拟客户买蛋糕
public class Client { public static void main(String[] args) { Cake circleCake = new CircleCake(); System.out.println(circleCake.cakeName() + ":" + circleCake.cakePrice()); Cake rectangleCake = new RectangleCake(); System.out.println(rectangleCake.cakeName() + ":" + rectangleCake.cakePrice()); circleCake = new AddMangoTaste(circleCake); System.out.println(circleCake.cakeName() + ":" + circleCake.cakePrice()); rectangleCake = new AddStrawberryTaste(rectangleCake); System.out.println(rectangleCake.cakeName() + ":" + rectangleCake.cakePrice()); } }
装饰者模式的优缺点
优点:
1、目的在于扩展对象的功能。装饰者模式提供比继承更好的灵活性。装饰是动态的,运行时可以修改的;继承是静态的,编译期便已确定好。
2、通过使用不同的装饰类及对他们的排列组合,可以创造出许多不同行为的组合。
缺点:
1、 产生很多的小对象,大量的小对象会占用内存。
2、 组合方式很多,很容易出错。
原文:https://www.cnblogs.com/hhd-shuai/p/12657180.html