23种设计模式之一— — — —装饰模式详细介绍与讲解

装饰模式详细讲解

一、定义

装饰模式(别名:包装器)

装饰模式(Decorator Pattern)是结构型的设计模式,它允许在运行时动态地向对象添加新的职责或功能,同时保持对象的原始类不变。通过使用装饰器模式,可以在不修改现有代码的基础上扩展对象的功能,

二、装饰模式结构

核心思想

1.动态扩展 :在不改变原类结构和继承关系的情况下,动态地为对象添加功能。
2.包装对象 :通过创建一个包装对象(装饰器)来包裹真实对象,增加额外功能。
3.接口一致性 :装饰器与真实对象有相同的接口,确保客户端能以相同的方式与两者交互。
4.开闭原则 :对扩展开放,对修改关闭。新的功能通过添加装饰器实现,而不是修改原类。
5.灵活组合:允许通过组合多个装饰器来创建功能更为丰富的对象

模式角色

1.抽象组件(Component) :定义一个接口,用于规范准备接收附加责任的对象(即被装饰对象)。
2.具体组件(ConcreteComponent) :实现抽象组件接口,是装饰器要装饰的真实对象。
3.装饰器(Decorator) :持有一个抽象组件的引用,并继承抽象组件的接口。它既可以使用所持有的引用调用被装饰的组件的方法,也可以增加新的功能。
4.具体装饰器(ConcreteDecorator) :实现装饰器接口并给具体组件添加职责。它通常包含对具体组件的引用,以及一个或多个用于增加功能的额外方法。

这些角色在装饰模式中的交互方式是:

  • 抽象组件定义了所有装饰器对象和被装饰对象需要实现的接口。
  • 具体组件实现了抽象组件接口,是准备被装饰的对象。
  • 装饰器持有一个对抽象组件的引用,并且实现了抽象组件接口。它可以使用这个引用来调用被装饰对象的方法,并在调用前后添加新的功能。
  • 具体装饰器实现了装饰器接口,并且给具体组件添加新的职责。它通常包含一个指向被装饰对象的引用,以及用于实现附加功能的代码。

模式的UML类图

应用场景

  • 当需要为单个对象提供多种不同的行为或者表现形式时。
  • 需要向一个已经存在的类中添加功能,但又不希望修改该类的源代码或继承其子类时
  • 组合对象:当需要组合多个对象来创建一个具有更多功能的对象时,装饰模式是一个很好的选择。通过递归组合方式,可以构建出一个具有多种功能的对象。例如,在文件系统中,文件夹可以被视为一个特殊的文件,它可以包含其他文件和文件夹。使用装饰模式,可以将文件夹装饰为一个包含额外功能的对象,如支持加密、压缩等

模式优点

  • 动态地给对象添加功能,相比生成子类更加灵活、透明。
  • 无需修改原有类就可以扩展功能,符合开闭原则。
  • 装饰器可以被组合,以便在运行时动态地、多次地添加多个职责。

模式缺点

  • 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
  • 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
  • 不易调试:由于装饰器模式涉及到多个对象的交互,调试可能会变得相对困难。特别是当装饰器链很长时,追踪请求和响应的路径可能会变得复杂。

实例演示

图示

鸡腿堡应用:

代码演示

java 复制代码
package ZhuangShiMoShi;

public abstract class Humburger {
	protected String name;

	public String getName() {
		return name;
	}

	public abstract double getPrice();

}

package ZhuangShiMoShi;

public class ChickenBurger extends Humburger {
	public ChickenBurger(){
		name="鸡腿堡";
	}
	public double getPrice(){
		return 10;
	}
	

}

package ZhuangShiMoShi;

public abstract class Condiment extends Humburger {
	protected Humburger humburger;
	public abstract String getName();

}

package ZhuangShiMoShi;

public class Chilli extends Condiment {
	public Humburger hum;

	public Chilli(Humburger hum) {
		this.hum = hum;
	}

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return hum.getName() + " 加辣椒";
	}

	@Override
	public double getPrice() {
		// TODO Auto-generated method stub
		return hum.getPrice();
	}

}

package ZhuangShiMoShi;

public class Lettuce extends Condiment {
	public Humburger hum;

	public Lettuce(Humburger hum) {
		this.hum = hum;
	}

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return hum.getName()+" 加生菜";
	}

	@Override
	public double getPrice() {
		// TODO Auto-generated method stub
		return hum.getPrice()+1.5;
	}

}

测试类:

java 复制代码
package ZhuangShiMoShi;

public class Test {
	public static void main(String[] args) {
		Humburger hum = new ChickenBurger();
		System.out.println(hum.getName() + " 价钱:" + hum.getPrice());
		Lettuce lettuce=new Lettuce(hum);
		System.out.println(lettuce.getName()+" 价钱:"+lettuce.getPrice());
		Chilli chilli1=new Chilli(hum);
		System.out.println(chilli1.getName()+" 价钱:"+chilli1.getPrice());
		Chilli chilli2=new Chilli(lettuce);
		System.out.println(chilli2.getName()+" 价钱:"+chilli2.getPrice());
	}

}

运行结果

该代码主体是鸡腿堡,可以选择通过添加生菜、酱、辣椒等等许多其他的配料,并根据选择的配料计算相应的价格。
博主用心写,读者点关注;互动传真情,知识不迷路

相关推荐
MY_TEUCK5 小时前
Sealos 平台部署实战指南:结合 Cursor 与版本发布流程
java·人工智能·学习·aigc
我爱cope5 小时前
【从0开始学设计模式-10| 装饰模式】
java·开发语言·设计模式
朝新_6 小时前
【Spring AI 】图像与语音模型实战
java·人工智能·spring
RH2312116 小时前
2026.4.16Linux 管道
java·linux·服务器
zmsofts6 小时前
java面试必问13:MyBatis 一级缓存、二级缓存:从原理到脏数据,一篇讲透
java·面试·mybatis
sg_knight8 小时前
设计模式实战:责任链模式(Chain of Responsibility)
python·设计模式·责任链模式
aq55356008 小时前
编程语言三巨头:汇编、C++与PHP大比拼
java·开发语言
我是无敌小恐龙9 小时前
Java SE 零基础入门Day01 超详细笔记(开发前言+环境搭建+基础语法)
java·开发语言·人工智能·opencv·spring·机器学习
心态与习惯9 小时前
Julia 初探,及与 C++,Java,Python 的比较
java·c++·python·julia·比较
一叶飘零_sweeeet9 小时前
优秀文章合集
java