一、装饰模式概述
装饰模式:用于动态地给一个对象增加一些额外的职责。
就扩展功能而言,装饰模式提供了一种比使用子类更加灵活的替代方案,它是一种对象结构型模式。
二、装饰模式结构与实现
2.1 装饰模式结构
包含4个角色:
1,Component(抽象构件):是具体构件类和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法;
2,ConcreteComponent(具体构件):实;了在抽象构件中声明的方法,装饰类可以给他增加额外的职责。
3,Decorator(抽象装饰类):用于给具体构件增加职责,但是具体职责在其子类中实现;
4,ConcreteDecorator(具体装饰类):负责向构件中添加新的职责。
2.2 装饰模式实现
//充当抽象构件的角色
/**
* 抽象构建类
*/
public abstract class Phone {
/**
* 接收来电的方法
*/
public abstract void incomingTelegram();
}
//充当具体构件的角色
/**
* 具体构件类
*/
public class HuaweiPhone extends Phone {
@Override
public void incomingTelegram() {
System.out.println("来电时发出声音提醒");
}
}
//充当抽象装饰类的角色
/**
* 抽象装饰类
*/
public class PhoneDecorator extends Phone {
Phone phone;
public PhoneDecorator(Phone phone) {
this.phone = phone;
}
@Override
public void incomingTelegram() {
phone.incomingTelegram();
}
}
//充当具体装饰类的角色
/**
* 具体装饰类
*/
public class JarPhoneDecorator extends PhoneDecorator{
public JarPhoneDecorator(Phone phone) {
super(phone);
}
@Override
public void incomingTelegram() {
addJar();
super.incomingTelegram();
}
public void addJar() {
System.out.println("来电时发出震动");
}
}
/**
* 具体装饰类
*/
public class FlickeringPhoneDecorator extends PhoneDecorator{
public FlickeringPhoneDecorator(Phone phone) {
super(phone);
}
@Override
public void incomingTelegram() {
addFlickering();
super.incomingTelegram();
}
public void addFlickering() {
System.out.println("来电时有灯光闪烁提示");
}
}
//客户端
public class Client {
public static void main(String[] args) {
/**
* 案例需求描述:
* 最简单的手机在接收到来电时候会发出声音提醒主人,
* 现在需要为该手机添加一项功能,
* 在接收来电时除了有声音还能产生震动;
* 或者来电时不仅能够发声,产生震动,而且还有灯光闪烁提示。
* 试用装饰模式来模式手机功能升级的过程。
*
*/
Phone p1, p2, p3;
p1 = new HuaweiPhone();
p2 = new JarPhoneDecorator(p1);
p3 = new FlickeringPhoneDecorator(p2);
p1.incomingTelegram();
System.out.println("------");
p2.incomingTelegram();
System.out.println("------");
p3.incomingTelegram();
}
}
三、装饰模式的优缺点和适用环境
3.1 装饰模式的优点
- 对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加;
- 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合可以创造出很多不同行为的组合,得到功能更加强大的对象;
- 具体构建类和具体装饰类可以独立变化,用户可以更具需要增加新的具体构件类和具体装饰类,原有类库代码无需改变,符合开闭原则。
3.2 装饰模式的缺点
- 使用装饰模式进行系统设计时将产生很多小对象;
- 装饰模式比继承更加易于出错,排错也更加困难,对于多次装饰的对象,在调试时寻找错误可能需要逐级排查,较为繁琐。
3.3 装饰模式的适用环境
- 在不影响其他对象的情况下以动态、透明的方式给单个对象增加职责;
- 当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时,可以用装饰模式。
【参考文献】:
本文是根据刘伟的《Java设计模式》一书的学习笔记,仅供学习用途,勿做其他用途,请尊重知识产权。
【本文代码仓库】:https://gitee.com/xiongbomy/java-design-pattern.git