14.盔甲?装甲?装饰者模式!

人类的军工发展史就是一场矛与盾的追逐,矛利则盾坚,盾愈坚则矛愈利。在传统的冶金工艺下,更坚固的盾牌和盔甲往往意味着更迟缓笨重的运动能力和更高昂的移动成本。从战国末期的魏武卒、秦锐士,到两宋之交的铁浮图、重步兵,再到有明一朝的边军四大营、神机营,最后到现代战争的各式主战坦克…防御越高,移动越慢。
在这里插入图片描述

甲辰年正月初三,窗外的声声爆竹撩拨着执笔人的心绪。笔者每每读到一些战史时都会有一种幻想,在没有火器的时代,如果身穿一副重型盔甲,刀劈不入,箭射不穿,那不就是高达一样的存在吗?
实际上,在没有技术爆炸的情况下,传统的重型盔甲会让普通人寸步难行,防御每提高一分,重量必然也会提高一分。这种层层嵌套的规律,特别契合装饰者模式的设计理念。

一言

就像打包一个快递一样,装饰者模式动态的将新功能附加在对象上,在对象功能扩展方面,它比继承更有弹性,也体现了开闭原则。

从盔甲到装甲

在这里插入图片描述

好的各位,欢迎来到奇珍异品收藏室,在你的面前有原始人的兽皮衣、秦始皇的金缕玉衣、唐太宗的鳞甲、史塔克的马克四十、反浩克装甲和T62主战坦克。
我需要一个程序,在我穿上了不同盔甲又登上了不同的载具之后,算出体系的整体重量。

进击的莽撞人

“大哥,这题俺会!看俺的!”
在这里插入图片描述
莽撞人搓搓手,开始展示他的设计思路:
在这里插入图片描述
在莽撞人展示思路的同时,我们不妨先尝试理解下问题的本质。
在我们的面前,有大量的盔甲和装甲,我既可以穿着马克装甲进入反浩克装甲,也可以穿着原始人的兽皮衣进入T62主战坦克…
这种组合有很多种
,如果求具体的数值一定是一个很经典的排列组合高考题。
在这种情况下,莽撞人的设计思路的确能够暂时的解决业务需求。但是从长远的设计角度考虑,这种设计会产生很多的类,如果奇珍异品收藏室的宝物越来越多,类的数量就会倍增进而引发类爆炸。
考虑到莽撞人的高爆发,我们选择悄咪咪的离开。

才出狼窝又如虎穴

“哥哥!我!他的方案有瑕疵,我有个大胆的想法,你给看看!”
未成想,转角遇到另一个莽撞人。
在这里插入图片描述
“哥哥,不就是类爆炸的问题嘛?你看我的,咱把不能贴身穿的都给它做成内置的,怎么样?”
在这里插入图片描述
不得不说,这种方案确实没有之前那么鲁莽,但是问题的本质并不是类爆炸,而是由类爆炸带来的扩展性低的问题。现在通过内置的确在一定程度上缓解了类爆炸的问题,但是并没有解决宝物新增带来的系统难以维护的问题。

装饰者模式

终于,两位莽撞人收了神通,准备听听我们的方案。
其实我们通过仔细拆解需求可以发现,是可以将这些宝物分为主体和包装的,这一点在第二个方案里实际上也有体现,只不过第二个方案并没有处理好主体和包装的关系。
主体其实就是莽撞人所说的贴身穿的,比如各式盔甲、马克40等等,而包装则是像T62坦克这种不一定会被方案选中的装甲。主体是被装饰者,包装是装饰者,装饰者可以聚合被装饰者。
举个例子:我穿着马克40装甲坐在两栖作战车上的T60坦克里。贴身的马克装甲是被装饰者,T62和两栖车都是装饰者。
在这里插入图片描述

设计

在这里插入图片描述
通过weight()递归计算体系重量。

代码实现

抽象

public abstract class AbsSuit {
    public String des;
    private float wit = 0.0f;
    public abstract float weight();
    //setter&getter
}

装备&盔甲

public class Suit extends AbsSuit{
    @Override
    public float weight() {
        return super.getWit();
    }
}

马克40

public class Mark40 extends Suit{
    public Mark40() {
        setDes("马克40装甲已装配");
        setWit(30000);
    }
}

包装抽象

public class Decorator extends Suit{
    private Suit obj;
    public Decorator(Suit obj) {
        this.obj = obj;
    }
    @Override
    public float weight() {
        return super.getWit()+obj.weight();
    }
    @Override
    public String getDes() {
        return super.des+" "+super.getWit()+"&&"+obj.getDes();
    }
}

T62主战坦克

public class T62 extends Decorator{
    public T62(Suit suit) {
        super(suit);
        setDes("T62主战坦克已装配");
        setWit(70000);
    }
}

两栖运输车

public class TranCar extends Decorator{
    public TranCar(Suit suit) {
        super(suit);
        setDes("两栖运输车已装配");
        setWit(10000);
    }
}

称重工厂

public class XFactory {
    public static void main(String[] args) {
        Suit suit = new Mark40();
        System.out.println(suit.getDes());
        System.out.println("称重1=" + suit.weight() + "kg");
        suit = new T62(suit);
        System.out.println(suit.getDes());
        System.out.println("称重2=" + suit.weight() + "kg");
        suit = new TranCar(suit);
        System.out.println(suit.getDes());
        System.out.println("称重3=" + suit.weight() + "kg");
    }
}

____启动?

在这里插入图片描述

装饰者模式在JDK IO 的应用

在JDK 的 IO 机构中,InputStream族的设计模式就是装饰者模式。
在这里插入图片描述
InputStream是抽象类,FilterInputStream是装饰者,InputStream及其子类都是被装饰对象。
在这里插入图片描述

相信大家通过以上的例子会对装饰者模式有了进一步的了解。在我看来,装饰者模式就是一个套盒子的游戏,它通过巧妙的嵌套和递归,将原本需要类扩展的逻辑封装在了关系内,在不违反开闭原则的前提下使得代码更加的优雅,便于维护和理解。


关注我,共同进步,龙年大吉。——Wayne

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/384404.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Roop的安装教程

roop插件的安装,并不容易 并且最好就是在电脑本地完成,因为涉及到C、visual studio软件,并且还需要在电脑本地放置一些模型,用autoDL其实也有镜像,但是需要数据扩容至少100G,烧钱。。。 电脑本地&#xff0…

javaweb物业管理系统jsp项目

文章目录 物业管理系统一、系统演示二、项目介绍三、系统部分功能截图四、部分代码展示五、底部获取项目源码(9.9¥带走) 物业管理系统 可用作javaweb项目、servlet项目、jsp项目的项目设计 一、系统演示 物业管理系统 二、项目介绍 语言&a…

ChatGPT高效提问—prompt常见用法(续篇)

ChatGPT高效提问—prompt常见用法(续篇) ​ 对话式prompt适用于模拟各种交流情境。若我们意图探索在特殊场合下可能出现的对话情景,或者模拟一段对话流程,可以采用这种方法,通过精准的prompt指令,引导Chat…

多视图特征学习 Multi-view Feature Learning既可以被看作是一种学习框架,也可以被看作是一种具体的学习算法!

Multi-view Feature Learning 1.多视图特征学习Multi-view Feature Learning的基本介绍总结 1.多视图特征学习Multi-view Feature Learning的基本介绍 多视图特征学习是一种利用多视图数据集来进行联合学习的机器学习方法。多视图数据指的是对同一事物从多种不同的途径或角度进…

监测Nginx访问日志502情况后并做相应动作

今天带大家写一个比较实用的脚本哈 原理: 假设服务器环境为lnmp,近期访问经常出现502现象,且502错误在重启php-fpm服务后消失,因此需要编写监控脚本,一旦出现502,则自动重启php-fpm服务 场景: 1…

人脸追踪案例及机器学习认识

1.人脸追踪机器人初制 用程序控制舵机运动的方法与机械臂项目完全相同。 由于摄像头的安装方式为上下倒转安装,我们在编写程序读取图像时需使用 flip 函数将 图像上下翻转。 现在,只需要使用哈尔特征检测得到人脸在图像中的位置,再指示舵机运…

C++内联函数深入讲解

用法: 在函数的返回值前面加上inline,例如: 作用: 内联函数的存在其实是为了解决c语言中一些问题,比如有一个频繁调用的小函数,每次调用都需要建立栈帧,压栈出栈,减少了效率&#xf…

【复现】litemall商场系统后台弱口令漏洞_47

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一: 四.修复建议: 五. 搜索语法: 六.免责声明 一.概述 litemall是一个简单的商场系统,基于现有的开源项目,重新实现一个完整的前后端项目,包含小程序…

单链表基础知识点

单链表的读取 对于单链表实现获取第i个元素的数据的操作 GetElem&#xff0c;在算法上&#xff0c;相对要麻烦一些。 获得链表第i个数据的算法思路: 声明一个结点p指向链表第一个结点&#xff0c;初始化j从1开始;当j<i时&#xff0c;就遍历链表&#xff0c;让p的指针向后移…

如何通过ETL实现快速同步美团订单信息

一、美团外卖现状 美团作为中国领先的生活服务电子商务平台&#xff0c;其旗下的美团外卖每天承载着大量的订单信息。这些订单信息需要及时入库、清洗和同步&#xff0c;但由于数据量庞大且来源多样化&#xff0c;传统的手动处理方式效率低下&#xff0c;容易出错。比如&#…

嵌入式中详解 ARM 几个常见的寄存器方法

大家好&#xff0c;今天来聊聊对于ARM几个特殊寄存器的理解&#xff0c;FP、SP和LR。 1、介绍 FP&#xff1a;栈顶指针&#xff0c;指向一个栈帧的顶部&#xff0c;当函数发生跳转时&#xff0c;会记录当时的栈的起始位置。 SP&#xff1a;栈指针&#xff08;也称为栈底指针&…

2本对微服务拆分有帮助的书

迁移到云原生应用架构 可在线观看的免费书籍 https://pivotal.io/platform-as-a-service/migrating-to-cloud-native-application-architectures-ebook 微服务架构设计模式 世界十大架构师之一&#xff1a;克里斯理查森著

161基于matlab的快速谱峭度方法

基于matlab的快速谱峭度方法&#xff0c;选择信号峭度最大的频段进行滤波&#xff0c;对滤波好信号进行包络谱分析。输出快速谱峭度及包络谱结果。程序已调通&#xff0c;可直接运行。 161 信号处理 快速谱峭度 包络谱分析 (xiaohongshu.com)

2024年世界听力日活动的主题是什么?

改变思维模式&#xff1a;让所有人的耳和听力保健成为现实&#xff01; Let’s make ear and hearing care a reality for all! 据 世界卫生组织 报道&#xff1a;在全球范围内&#xff0c;超过 80% 的耳和听力保健需求仍未得到满足 &#xff1b; 未得到解决的听力损失每…

【NodeJS】006- API模块与会话控制介绍d

1.简介 1.1 接口是什么 接口是 前后端通信的桥梁 简单理解&#xff1a;一个接口就是 服务中的一个路由规则 &#xff0c;根据请求响应结果 接口的英文单词是 API (Application Program Interface)&#xff0c;所以有时也称之为 API 接口 这里的接口指的是『数据接口』&#…

视觉slam十四讲学习笔记(三)李群与李代数

1. 理解李群与李代数的概念&#xff0c;掌握 SO(3), SE(3) 与对应李代数的表示方式。 2. 理解 BCH 近似的意义。 3. 学会在李代数上的扰动模型。 4. 使用 Sophus 对李代数进行运算。 目录 前言 一、李群李代数基础 1 群 2 李代数的引出 3 李代数的定义 4 李代数 so(3…

【JVM篇】分析并讲解字节码文件

文章目录 &#x1f354;字节码文件⭐打开字节码文件的工具⭐字节码文件的组成✨具体分析 &#x1f354;字节码文件 字节码文件是一种中间表示形式&#xff0c;它通常由编译器将高级编程语言&#xff08;如Java、Python等&#xff09;源代码编译而成。字节码文件包含了程序的指…

Linux第50步_移植ST公司的linux内核第2步_编译ST公司的linux源码和修改网络驱动

1、修改“linux-5.4.31”目录下的“Makefile” 1)、使用VSCode打开“linux-5.4.31.code-workspace” 2)、点击“linux-5.4.31”目录下的“Makefile” 3)、点击“编辑”&#xff0c;点击“查找”&#xff0c;输入“CROSS_COMPILE回车”&#xff0c;找到“ARCH ? $(SUBARCH)”…

SpringCloud-高级篇(二十二)

前面解决了消息的可靠性、消息的延迟问题&#xff0c;消息的堆积的问题&#xff0c;下面研究mq可用性、并发能力问题&#xff0c;这就需要mq集群来实现了 一&#xff1a;集群分类 &#xff08;1&#xff09;普通集群 创建一个节点&#xff1a; 8082、8083也可以看到这个队列&…

Qt可视化大屏布局

科技大屏现在非常流行&#xff0c;这里分享一下某个项目的大屏布局&#xff08;忘了源码是哪个博主的了&#xff09; 展示 这个界面整体是垂直布局&#xff0c;分为两个部分&#xff0c;标题是一个部分&#xff0c;然后下面的整体是一个layout布局&#xff0c;为另外一部分。 l…
最新文章