装饰模式能够在不改变原来对象结构和功能的前提下,动态的给对象增加新的功能,相比于使用子类扩展的方式,装饰模式更加的灵活。
(1)抽象构件类:为具体构件类和装饰类提供抽象方法。
(2)具体构建类:是抽象构建类的子类,实现抽象方法,用于定义具体的构件对象。
(3)抽象装饰类:是抽象构件类的子类,维护了一个指向抽象构件类的引用,同时提供构造方法或者set方法设置具体构件类。提供了设置装饰的抽象方法。
(4)具体装饰类:是抽象装饰类的子类,实现了其装饰的抽象方法。负责向构建中添加新的职责,每一个具体装饰类都定义了一些新的行为,可以调用抽象装饰类中定义的方法,并可以增加新的职责用以扩充对象的行为。
(1)装饰者模式和继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性
(2)通过使用不同的具体装饰者类及他们不同的组合顺序,可以得到不同装饰后具有不同行为或者状态的对象
(3)符合开闭原则(对扩展开放,对修改关闭)
(4)动态扩展类功能,比类继承灵活,且对客户端透明
(5)继承关系的一种替代方案,相比于类继承的父子关系,装饰模式更像是一种组合关系(is-a)
(6)可以对同一个被装饰对象进行多次装饰,创建出不同行为的符合功能
(1)多层装饰比较复杂
(2)装饰嵌套过多,会产生过多小对象(每个装饰层都创建一个相应的对象)
(3)装饰嵌套过多,易于出错,且调试排查比较麻烦(需要一层一层对装饰器进行排查,以确定是哪一个装饰层出错)
(1)需要扩展一个类的功能,或给一个类增加附加功能
(2)需要动态地给一个对象增加功能,且这些功能可以再动态的撤销
(3)需要为一批兄弟类进行改装或加装功能
以手机为例,从刚开始的基础版手机只具备打电话、发短信的功能,到后来可以安装QQ、浏览网页的功能,再到现在的智能手机可以安装各种各样的app,堪比一个小型电脑。手机的发展可以看做一个装饰者模式,以打电话、发短信为最基本的功能,QQ、浏览器、微信、王者荣耀等可以动态添加到手机的功能中。
public abstract class MobilePhone {
/**
* 抽象操作方法
*/
abstract void operation();
}
public class FirstGenerationPhone extends MobilePhone {
@Override
void operation() {
call();
sms();
}
private void call() {
System.out.println("打电话");
}
private void sms() {
System.out.println("发短信");
}
}
定义如何添加手机的附加功能
public class Decorate extends MobilePhone{
private MobilePhone mobilePhone;
public Decorate(MobilePhone mobilePhone){
this.mobilePhone = mobilePhone;
}
@Override
void operation() {
mobilePhone.operation();
}
}
添加QQ软件,除基础功能之外,添加QQ聊天功能
public class QQDecorate extends Decorate{
public QQDecorate(MobilePhone mobilePhone) {
super(mobilePhone);
}
@Override
void operation() {
super.operation();
qq();
}
private void qq(){
System.out.println("qq聊天");
}
}
添加微信软件
public class WeChatDecorate extends Decorate {
public WeChatDecorate(MobilePhone mobilePhone) {
super(mobilePhone);
}
@Override
void operation() {
super.operation();
chat();
}
private void chat() {
System.out.println("微信聊天");
}
}
添加王者荣耀软件
public class ArenaGameDecorate extends Decorate{
public ArenaGameDecorate(MobilePhone mobilePhone) {
super(mobilePhone);
}
@Override
void operation() {
super.operation();
play();
}
private void play(){
System.out.println("玩儿王者荣耀");
}
}
实现
public class Client {
public static void main(String[] args) {
System.out.println("第一代手机");
FirstGenerationPhone phone = new FirstGenerationPhone();
phone.operation();
System.out.println("\n安装QQ之后的功能");
QQDecorate qqDecorate = new QQDecorate(phone);
qqDecorate.operation();
System.out.println("\n安装微信之后的功能");
WeChatDecorate weChatDecorate = new WeChatDecorate(qqDecorate);
weChatDecorate.operation();
System.out.println("\n安装王者荣耀之后的功能");
ArenaGameDecorate arenaGameDecorate = new ArenaGameDecorate(weChatDecorate);
arenaGameDecorate.operation();
}
}
效果: