设计模式-装饰器模式
时间:2022-07-25
本文章向大家介绍设计模式-装饰器模式,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
背景
现代人每个人基本都会有一部手机,有的有好几部,正常情况下买手机有很多套餐,比如裸机、裸机+贴膜、裸机+贴膜+手机壳等,但是不一定每个人在购买的时候都一定会贴膜,所以个性化需求就出来了,所以这个贴膜,总不能一出厂就有了,一般后续服务中增加的,属于装饰品,而装饰器模式就解决该问题。
装饰器模式是什么?
定义:装饰器动态给一个对象添加一些额外的功能/职责,装饰模式比生成子类更为灵活。 抽象构件(component)角色 :用来规范被装饰的对象,一般为统一接口输出。具体构件(concreteComponent )角色 :被装饰的类,本身也是具备功能类。装饰(decorator)角色 :持有一个构件对象的实例。并定义一个跟抽象构件一致的接口。具体 (concreteDecorator ) 装饰角色 :负责给具体构件添加附加职责的类。在实际使用中多数情况下装饰角色和具体装饰角色可能由一个类来承担。其实也就是给你手机加些装饰器,而这些装饰器可有可无,根据你的选对来的,贴不贴膜,要不要手机壳,非原厂出厂就有。
装饰器模式可以干嘛?
对原有的对象或者功能动态增加功能/职责,很好的起到一个动态增删。并且代码不会浸入性低,新增的功能增减不会影响原来的功能;
就比如一部手机买到手是裸机,新贴上膜和手机壳,不会影响这个手机的使用,并且这个壳和膜不想用不会影响手机的功能。
优点:
代码易读:使用装饰器模式代码简单易读,业务逻辑清晰; 拓展性强:功能动态增删影响低; 减少耦合,低侵入:由于解决了传统的继承或者说在原来的对象去增加功能减少了很大的耦合和侵入性也很少;
缺点:
多层装饰导致系统复杂:因为如果装饰器可以有好多层所以会导致系统过于复杂,所以建议不要过于复杂的装饰。
装饰器类图
实现代码
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
/**
* @Auther: csh
* @Date: 2020/5/28 18:02
* @Description:抽象的手机
*/
public interface IPhone {
//打电话
void callUp(String number);
//上网
void internet(int newWork);
//基本功能
void printFunction();
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:06
* @Description:小米手机
*/
public class XMPhone implements IPhone {
@Override
public void callUp(String number) {
System.out.println("小米手机打电话:"+number);
}
@Override
public void internet(int newWork) {
System.out.println("上的网络"+newWork+"G");
}
@Override
public void printFunction() {
System.out.println("小米手机有手电话和上网功能");
}
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:05
* @Description:华为手机
*/
public class HWPhone implements IPhone {
@Override
public void callUp(String number) {
System.out.println("正在打电话:"+number);
}
@Override
public void internet(int newWork) {
System.out.println("上的网络"+newWork+"G");
}
@Override
public void printFunction() {
System.out.println("华为手机有手电话和上网功能");
}
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:07
* @Description:抽象的修饰器
*/
public abstract class IPhoneDecorator implements IPhone {
protected IPhone phone;
public IPhoneDecorator(IPhone phone) {
this.phone = phone;
}
@Override
public void printFunction() {
phone.printFunction();
}
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:10
* @Description:手机壳装饰器
*/
public class PhoneShellDecorator extends IPhoneDecorator {
public PhoneShellDecorator(IPhone phone) {
super(phone);
}
@Override
public void callUp(String number) {
phone.callUp(number);
}
@Override
public void internet(int newWork) {
phone.internet(newWork);
}
@Override
public void printFunction() {
super.printFunction();
this.setShell();
}
private void setShell(){
System.out.println("加装了手机壳");
}
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:10
* @Description:
*/
public class PhoneFilmDecorator extends IPhoneDecorator {
public PhoneFilmDecorator(IPhone phone) {
super(phone);
}
@Override
public void callUp(String number) {
phone.callUp(number);
}
@Override
public void internet(int newWork) {
phone.internet(newWork);
}
@Override
public void printFunction() {
super.printFunction();
this.setFilm();
}
private void setFilm(){
System.out.println("贴了膜");
}
}
/**
* @Auther: csh
* @Date: 2020/5/28 18:16
* @Description:案例
*/
public class Client {
public static void main(String[] args) {
HWPhone hwPhone = new HWPhone();
hwPhone.printFunction();
PhoneFilmDecorator phoneFilmDecorator = new PhoneFilmDecorator(hwPhone);
XMPhone xmphone = new XMPhone();
phoneFilmDecorator.printFunction();
PhoneShellDecorator phoneShellDecorator = new PhoneShellDecorator(xmphone);
phoneShellDecorator.printFunction();
}
}
结果
华为手机有手电话和上网功能
华为手机有手电话和上网功能
贴了膜
小米手机有手电话和上网功能
加装了手机壳
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
最后
装饰器在日常开发过程中应用广泛,比如类似这种需求迭代比较快,而又不确定这个属性/方法是否以后会一直保留,在这种不确定性的场景下装饰器再适合不过了。或者说原来的功能已很稳定不想影响到原来的功能,并且该功能只是个性化给某个需求专用,那就建议使用。
- hdu 3635 Dragon Balls (带权并查集)
- 沃趣QFusion vs MGR、MGC面面观
- Redis的配置、启动、操作及关闭
- 剖析Go编写的Socket服务器模块解耦及基础模块的设计
- hdu 3172 Virtual Friends (映射并查集)
- Vue 大法好
- Python:ip地址处理模块
- Oracle 12c系列(四)|资源隔离之IO、内存、CPU
- Python:gethostbyname获取本地ip地址
- Oracle 12c系列(五)|PDB Refresh
- hdu 2473 Junk-Mail Filter (并查集之点的删除)
- Python:platform获取操作系统详细信息
- java版本的学生管理系统
- Python:获取目录下指定后缀的文件
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 从源码打造云原生时代的「Linux」——Kubernetes
- Django-models & QuerySet API
- [奇淫巧技]GitHub个人页的新玩法
- 一致性哈希的分析与实现
- 关系型数据库查询语言 SQL 和图数据库查询语言 nGQL 对比
- 目标检测之评价指标 - mAP
- sass的基础用法
- Golang Gin 实战(十四)| 文件托管、反向代理百度网站、自实现API网关
- ceph修复pg inconsistent
- 基于kubernetes的kong网关实战
- 移动端适配必须掌握的基本概念和适配方案
- [OHIF-Viewers]医疗数字阅片-医学影像-Redux中的reducer到底是什么,以及它为什么叫reducer?
- 【从零开始用Swift开发一个iOS应用(仿微博)】开篇-1. demo上手体验
- 数据结构与算法-二维数组中的查找
- 卷积神经网络之 - GoogLeNet / Inception-v1