1、定义
装饰器模式(Decorator Pattern)也叫包装模式(Wrapper Pattern),是指在不改变原有对象的基础上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有独享的功能)。
核心:功能扩展,透明的并且可以动态扩展对象的功能。
主要用于动态的扩展类的功能。其实现原理为:
让装饰器实现被包装类(Concrete Component)相应的接口(Component)(使得装饰器与被扩展类类型一致),并在构造函数中传入该接口(Component)对象,然后就可以在接口需要实现的方法中在被包装类对象的现有功能上添加新功能了。而且由于装饰器与被包装类属于同一类型(均为Component),且构造函数的参数为其实现接口类(Component),英雌装饰器模式具备潜逃扩展功能,这样我们就能使用装饰器模式一层一层的对最底层被包装类进行功能扩展了。
属于结构型模式
2、使用场景
1.用于扩展一个类的功能或给一个类添加附加职责;
2.动态的给一个对象添加功能,这些功能可以再动态的撤销。
3、组成
抽象组件(Component):可以是一个接口或者抽象类,其充当被装饰类的原始对象,规定了被装饰对象的行为;
具体组件(ConcreteComponent):实现/继承Component的一个具体对象,也叫作被装饰对象;
抽象装饰器(Decorator):通用的装饰ConcreteComponent的装饰器,其内部必然有一个属性指向Component抽象组件;起始线一般是一个抽象类,只要是为了让其子类按照其构造形式传入一个Component抽象组件,这是强制的通用行为(当然没如果系统中装饰逻辑单一,并不需要实现雨多装饰器,那么可直接省略该类,而直接实现一个具体装饰器即可);
具体装饰器(ConcreteDecorator):Decorator的具体实现类,理论上,每个具体装饰器都扩展了Component对象的一种功能。
总结:装饰器模式角色分配符合设计模式的历史替换原则,依赖倒置原则,从而使得其具备很强的扩展性,最终满足开闭原则。
4、应用场景
为对象扩展一些额外的职责,主要适用以下场景:
1、用于扩展一个类的功能或给一个类添加附加职责;
2、动态的给一个对象添加功能,这些工鞥呢可以再动态的撤销;
3、需要为一批的兄弟类进行改装或者加装功能。
装饰器在源码中的应用:
JDK中的IO相关的类,BufferedReader、InputStream、OutputStream等都应用到了装饰器模式。
5、优点
1、装饰器是继承的有力补充,比继承灵活,不改变原有对象的情况下动态的给一个独享扩展功能,即插即用;
2、通过使用不同装饰类自己这些装饰类的排列组合,可实现不通效果;
3、装饰器完全遵守开闭原则。
6、缺点
1、会出现更多的代码。更多的类,增加程序的复杂性;
2、动态装饰时,多层装饰会更复杂
7、装饰器模式与代理模式对比
1、装饰器模式就是一种特殊的静态代理模式;
2、装饰器模式强调自身的功能扩展,并且是透明(用户自定义)的扩展,可动态定制的扩展;
3、代理模式强调代理过程的控制。
8、实例应用
需求:根据不同权限访问网页的时候显示不同的导航栏。用装饰器模式实现:
需求分析:
导航栏功能:
1.问答2.文章3.精品课4.冒泡5.商城6.题库7.作业8.成长墙9.用户管理
权限等级:
a)游客 b)普通用户 c)VIP用户 d)管理员
不同权限所能看到的导航栏:
a:1 2 3 4 5
b:1 2 3 4 5 6
c:1 2 3 4 5 6 7 8
d:1 2 3 4 5 6 7 8 9
根据需求,把展示导航设计成抽象组件;
可以把12345
设计为基础组件,也就是被装饰对象;
根据不同的需求把6789
分别设计为具体装饰器;
整体设计类图如下:
1、权限:
2、导航栏装饰器:
3、整体类图:
4、代码实现:
(1)装饰器代码
// 导航接口===============================
public interface INovs {
/**
* @Description 导航栏展示
**/
public String showNovs();
}
// 公共导航==================================
public class PublicNovs implements INovs {
@Override
public String showNovs() {
return "问答 文章 精品课 冒泡 商城";
}
}
// 抽象装饰器,用于扩展功能================================
public abstract class AbstractDecorator implements INovs {
protected INovs iNovs;
public AbstractDecorator(INovs iNovs){
this.iNovs = iNovs;
}
}
// 成长墙装饰===============================================
public class GrowthWallNav extends AbstractDecorator {
public GrowthWallNav(INovs iNovs) {
super(iNovs);
}
@Override
public String showNovs() {
return iNovs.showNovs() + " 成长墙";
}
}
// 题库装饰===============================================
public class QustionNav extends AbstractDecorator {
public QustionNav(INovs iNovs) {
super(iNovs);
}
@Override
public String showNovs() {
return iNovs.showNovs() + " 题库";
}
}
// 作业装饰===============================================
public class TaskNav extends AbstractDecorator {
public TaskNav(INovs iNovs) {
super(iNovs);
}
@Override
public String showNovs() {
return iNovs.showNovs() + " 作业";
}
}
// 用户权限装饰============================================
public class UserManageNav extends AbstractDecorator {
public UserManageNav(INovs iNovs) {
super(iNovs);
}
@Override
public String showNovs() {
return iNovs.showNovs() + " 用户权限";
}
}
(2)权限代码
// 权限接口===============================================
public interface IAuthority {
/**
* @Description 根据权限展示导航
**/
String showNovsByAuthority();
}
// 游客权限===============================================
public class Visitor implements IAuthority {
@Override
public String showNovsByAuthority() {
return new PublicNovs().showNovs();
}
}
// 普通用户===============================================
public class OrdinaryUser implements IAuthority {
@Override
public String showNovsByAuthority() {
return new QustionNav(new PublicNovs()).showNovs();
}
}
// VIP用户================================================
public class VIPUser implements IAuthority {
@Override
public String showNovsByAuthority() {
return new QustionNav(new TaskNav(new GrowthWallNav(new PublicNovs()))).showNovs();
}
}
// 管理员==================================================
public class Admin implements IAuthority {
@Override
public String showNovsByAuthority() {
return new UserManageNav(new QustionNav(new TaskNav(new GrowthWallNav(new PublicNovs())))).showNovs();
}
}
(3)测试
public class Test {
public static void main(String[] args) {
// 游客访问
Visitor visitor = new Visitor();
System.out.println("游客访问:" + visitor.showNovsByAuthority());
System.out.println("=====================================");
// 普通用户访问
OrdinaryUser ordinaryUser = new OrdinaryUser();
System.out.println("普通用户访问:" + ordinaryUser.showNovsByAuthority());
System.out.println("=====================================");
// VIP用户访问
VIPUser vipUser = new VIPUser();
System.out.println("VIP用户访问:" + vipUser.showNovsByAuthority());
System.out.println("=====================================");
// 管理员访问
Admin admin = new Admin();
System.out.println("管理员访问:" + admin.showNovsByAuthority());
System.out.println("=====================================");
}
}
// 结果==============================================
游客访问:问答 文章 精品课 冒泡 商城
=====================================
普通用户访问:问答 文章 精品课 冒泡 商城 题库
=====================================
VIP用户访问:问答 文章 精品课 冒泡 商城 成长墙 作业 题库
=====================================
管理员访问:问答 文章 精品课 冒泡 商城 成长墙 作业 题库 用户权限
=====================================