Decorator模式中遭遇继承与聚合的冲突-Java基础-Java-编程开发

Java字节码逆向分析利器:Bytecode-Viewer核心功能与实战指南 Java字节码是Java源代码编译后的中间表示,它承载了程序的执行逻辑,但人类难以直接阅读。理解字节码结构和工作原理,对于深入学习Java虚拟机、性能优化和安全分析具有重要价值。通过反编译技术,可以将字节码转换回近似源代码的形式,这在调试无源码的第三方库、学习优秀框架实现、进行代码审计等工程实践中尤为关键。Bytecode-Viewer作为一款集成了CFR、Procyon等多个顶级反编译引擎的图形化工具,其多引擎对比和即时交互特性,能有效应对复杂的Lambda表达式和Switch语句分析,帮助开发者高效解决 阅读详情
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

一:背景:Decorator

*Decorator 常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这两种实体在Decorator 模式中是必须的。

*Decorator 定义:

动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator 模式相比用生成子类方式达到功能的扩充显得更为灵活。

*为什么使用Decorator?

我们通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。

使用Decorator 的理由是:这些功能需要由用户动态决定加入的方式和时机.Decorator 提供了"即插即用"的方法,在运行期间决定何时增加何种功能。

*对于该模式,初步归纳为

1.基本功能为接口

2.Decorator参数为接口本身也为接口以便为下一个Decorator的参数

3.基本功能类实现接口 并作为Decorator构造函数的参数,以便在此基础上添加新功能

4.额外功能由Decorator中的数据结构处理

二:问题

这是一段Decorator设计模式的实现例子如下:

基本功能:Counter类

需要添加的功能

1:上限控制

2:下限控制

import java.io.*;
class Counter{
private int value;
public Counter(int v){
System.out.println("init me here in The Counter with value!");
value=v;
}
public Counter(Counter cc){
System.out.println("init me here in The Counter with class!");
value=cc.value;
}
public int read_value(){
System.out.println("read me here The value is:" value);
System.out.println("read me here in The Counter!");
return value;
}
public void increment(){
System.out.println("increment me here in The Counter !");
value ;
}
public void decrement(){
System.out.println("decrement me here in The Counter !");
value--;
}
}
class Decorator extends Counter
{
Counter counter;
public Decorator(Counter c)
{
super(c);
System.out.println("init me here with class Decorator!");
}
}
class UpperLimit extends Decorator//上限控制
{
public UpperLimit(Counter c)
{
super(c);
counter=c;
System.out.println("init me here with class UpperLimit!");
}
public void increment()
{
if(counter.read_value()>20)
{
System.out.println("Too High");
}
else
{
System.out.println("increment me here with class UpperLimit!");
counter.increment();
}
}
/*public void decrement()
{
counter.decrement();
}
public int read_value()
{
return counter.read_value();
}*/
}
class LowerLimit extends Decorator//下限控制
{
public LowerLimit(Counter c)
{
super(c);
counter=c;
System.out.println("init me here in The Counter with class LowerLimit!");
}
public void decrement()
{
System.out.println("Class value :" read_value());
System.out.println("Dec value :" counter.read_value());
if(counter.read_value()<=0)
{
System.out.println(counter.read_value());
System.out.println("Too Low");
}
else
{
System.out.println("decrement me here in The Counter with class LowerLimit!");
counter.decrement();
}
}
/*public void increment()
{
counter.increment();
}
public int read_value()
{
return counter.read_value();
}*/
}
class CounterFactory
{
public static Counter createCounter(int value,int op)
{
switch(op)
{
case 1:
{
return new Counter(value);
}
case 2:
{
return new UpperLimit(new Counter(value));
}
case 3:
{
return new LowerLimit(new Counter(value));
}
default:
{
return new UpperLimit(new LowerLimit(new Counter(value)));
}
}
}
}
class Console
{
private static BufferedReader read=new BufferedReader(new InputStreamReader(System.in));
public static int readInt(String index){
System.out.println(index);
try{
return Integer.parseInt(read.readLine());
}
catch(Exception e){
return 0;
}
}
}
public class Q1s{
public static void main(String[] args){
System.out.println("Counter Type:");
System.out.println("1: Normal");
System.out.println("2: Upper Limit");
System.out.println("3: Lower Limit");
System.out.println("4: Upper & Lower Limit");
int option=Console.readInt("Enter Choice:");
Counter c = CounterFactory.createCounter(6,option);
int choice=1;
while(choice!=4){
System.out.println("1: Increment");
System.out.println("2: Decrement");
System.out.println("3: Read Value");
System.out.println("4: Exit");
choice=Console.readInt("Enter Choice:");
switch(choice){
case 1: c.increment(); break;
case 2: c.decrement(); break;
case 3: int v=c.read_value();
System.out.println("Value=" v);break;
}
}
}
}

按如下步骤运行出现明显问题:

1:选3,"Lower Limit",

2:选3,"Read Value" 获得的值是 6

3:选1,"Increment"(此后value值应为 7)

4:选3,"Read Value" 获得的值是 7(正确)

5:选2,"Decrement"(此后的value值应为 6)

6:选3,"Read Value" 获得的值为 7 (问题出现了)

考察 Upper Limit 时同样出现该问题

三:追究

从输出的追踪语句可以看出在class LowerLimit的decrement方法的开始两输出语句具有明显的指导意义而其中一方法是调用的来自父类的read_value()而另一个为聚合对象的read_value()。在上面步骤的第六步两句分别输出

Class value :7
Dec value :6

可见,有两份value的存在。问题是两份如何产生?

继续观察,工厂在开关语句选中case 3时调用的是

return new LowerLimit(new Counter(value));

其中新建一匿名对象为参数,继续追踪该过程,发现在class Decorator 中该匿名对象被Decorator的属性指向,而在指向之前,Decorator还把该匿名对象传给其父类,而父类取得该对象后仅仅是取出该对象中value的拷贝,由此有两份value存在:

1.在Decorator自身中(父类的value)

2.也在Decorator自身中(成员变量Counter的value属性)!

问题渐渐明朗,再次观察class LowerLimit,它仅仅实现了decrement()方法,也就是说,对LowerLimit调用read_value()与increment()时,其全部追溯到其父类中执行,而被作用的值value为第一类型值。对LowerLimit调用decrement()方法时,该方法是用其成员变量Counter的read_value()来执行的。此时被作用的值为第二类型值.所以会出现value值不同步的现象。

四:解决

很明显,解决方法在于仅使用其中一份value值,当然,Decorator本身的目的便在于避免使用继承,所以应当覆盖原有的方法,用成员变量的方法实现内部实现。也就是将代码中的注释去掉.

五:小结

父类获得了只是值的拷贝 而本身的聚合对象获得了(参数的)全部的引用否则 如果有方法没有覆盖原来的 则该方法将沿用父类的 在拷贝的值(value)上操作而被覆盖了的方法的将对本身聚合的对象中的值(value)进行操作 于是两value值产生分歧。

从Decorator模式本身的用意可知:在已有的类基础上的动态功能的添加(不是用继承来实现,以防太深,难以控制)所以,构造函数的参数应当也必须作为"已有的类基础"来对待,也就是说,自身的聚合对象必须是

该参数的引用,所有的方法也必须重造,否则将落入继承的陷阱。

大厂Python自动化测试面试题合集 题目:函数的作用是什么?调用函数的语法?答案:将独立功能代码封装成模块,复用代码;函数名(实参)。题目:函数 return 作用是什么?无 return 时函数返回什么?多返回值底层是什么类型?答案:返回函数执行结果;无 return 默认返回 None;return x,y,z 底层自动封装为元组。题目:函数四大参数类型分别是什么?定义顺序要求?答案:必选参数、默认参数、可变位置 * args、命名关键字、可变关键字 **kwargs;顺序:必选→默认→*args→命名关键字→**kwargs。 阅读详情

相关推荐

在Pycharm中配置Pyqt5工具(2023年新版教程)

在Pycharm中配置Pyqt5相关的三个工具:QtDesigner、PyUIC、PYRCC

网络技术和Python 2万+

decorator模式使用中遭遇继承与聚合的冲突问题

一:背景:Decorator*Decorator 常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这两种实体在Decorator 模式中是必须的.*Decorator 定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator 模式相比用生成子类方式达到功能的扩充显得更为灵活.*为什么

M.D.R 1261

立创·庐山派-K230-CanMV(嘉楠勘智)开发板通过ATK-ESP8266实现图像识别数据无线传输至原子云

本文详细介绍了如何使用立创·庐山派-K230-CanMV开发板,通过ATK-ESP8266 WIFI模块实现图像识别数据的无线传输至原子云平台。内容包括硬件连接、软件环境搭建、AT指令控制、原子云连接及数据上传的全过程,并提供了实用的调试技巧和常见问题解决方案,为物联网应用开发提供了完整实践指南。

potato的博客 743

java模式设计全接触

[全部文章]  工具软件  办公软件  操作系统  网络安全  设计在线  程序开发  专题教程  软件下载  论坛重点推荐:什么是设计模式  模式理论的基本思想其实起源于中国,是中国文化的固有思想。你,我,我们中每一个自幼受到中国思想熏陶的人,都自然具有这一基本思想。[全文阅读] Java中的模式   世上一直有一个神话:设计可以并且应该独立于实现的细节,设计通常被看作是一个抽象的概念而实现是一

fly_java的专栏 1394

STM32外围电路硬件解析

复位 :让MCU回到最开始的状态。并且从头开始,重新执行程序 我们什么时候需要复位? 1.烧录的时候 2.程序跑飞了的时候 3.上电复位(上电的时候需要复位) 复位方式: 1.上电复位: --- 一定要有 MCU的Reset是复位引脚,当这个引脚为低电平时,

qq_39577221的博客 1万+

Zabbix故障排查10051端口无法启动:zabbix-server.service: main process exited, code=exited, status=1/FAILURE

zabbix-server.service: main process exited, code=exited, status=1/FAILURE报错说与数据库失去连接。

" DevOps菜鸟(Xu JieHao)" 的博客 2258

JAVA面试题(1~95)《上》

1、面向对象的特征有哪些方面?  答:面向对象的特征主要有以下几个方面:  - 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。  - 继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性...

ywl470812087的博客 4964

Oracle 19c RAC安装踩坑实录:OpenSSH 8.x版本与OUI的“兼容性战争”及一劳永逸的解决思路

本文深入解析Oracle 19c RAC在Linux8环境中部署时遇到的OpenSSH 8.x版本兼容性问题,特别是[INS-06006]错误的根源与解决方案。从协议层分析冲突本质,提供SCP包装器技术、官方补丁应用指南及现代化部署体系构建三种解决方案,帮助企业高效完成RAC安装并规避类似问题。

weixin_42648844的博客 459

软件构造课程知识整理汇总

哈工大2022年春季学期软件构造课程总结:期末复习版本

z2984348的博客 2257

QuickFix Java 讲解(五)消息的收发与查看

本系列力求手把手教你怎样利用QuickFix Java 搭建自己的 FIX 协议收发平台,以及其中的注意事项。 所有源码的地址(免费): https://github.com/zongzhec/QuickFixPractise 这节我们讨论将Acceptor和Initiator启动以后,收到的消息极其查看方式。 6. 收发双方的通信 6.1. 启动后的通信和登录 为方便起见,这里我们使用统一的源码:https://github.com/zongzhec/QuickFixPractise ..

2247

射频电路设计——射频器件基础

本文仅供自己复习使用,请勿转载! 射频电路制作方法 MCM工艺 CMOS工艺 趋肤效应、深度 频率越高趋肤效应越明显 高频器件 高频电阻 绕线的比贴片的多一个电感,是因为绕线的因为是线绕制的,只有有线就会有电感,所以绕线电阻等效模型会比贴片的多一个电感 多晶硅电阻模型 深线性区MOS电阻 高频电阻的频率响应 记忆的话就后面的频率特性有点像电容的 高频电容 作用 单层贴片式电容 多层贴片式电容 MIM电容 MOM电容 由于是并联的,所以总的电容值是单个的直接相加 PN结电容 M.

输出每日所学,供大家学习使用 7153

软考-软件设计师-备考笔记

根据学习视频和一些资料整理的软考软件设计师考试笔记,2022年下半年通关

提子同学是我 1420

Macbook Pro Bootcamp 安装触控板驱动mac-precision-touchpad在Windows系统下实现更好的触控板操作

由于很多软件的限制,所以不得不在Windows和MacOS之间进行切换,然而,Windows下虽然Bootcamp提供了触控板的驱动,然而只能实现简单的上下滑动和点击等操作,而且在滑动页面的时候滑动非常不流畅,体验极差。 今天无意间发现了一款第三方撰写的驱动,可以较为完美地实现Macbook笔记本在Windows系统下的触控板操作支持,通过在我的2015款Macbook Pro(A1502)进行安装测试,感觉体验很不错,在这里分享给大家。 驱动来自于Github上的imbushu,他的项目地址如下: htt

博客 1万+

大二2个月通过中级软件设计师学习路线

软件设计师中级备考经验分享 去年我通过两三个月的努力成功通过了软件设计师中级考试。作为基础一般的考生,我想分享一下真实备考经历: 学习周期:建议至少预留2个月时间,网上所谓的"速成"并不靠谱 核心资料:B站zst_2001(炸薯条)的课程+真题刷题软件 备考策略: 上午选择题:反复记忆固定知识点 下午大题:理解原理而非死记硬背 算法题:从基础练起,如背包问题、N皇后问题 学习方法: 看视频做笔记→分类整理知识点→反复刷题修正 重点掌握计算机系统、软件工程、数据库、面向对象等核心章节 设计

2604_95920027的博客 1760

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

python3 核心笔记

本文主要是针对python3的一些核心要点做一些记录,感兴趣的可以关注和订阅。会持续更新,这个玩意学习一下,可以为数据分析和AI打下一定的基础。

yanghuashuiyue的专栏 621

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

软考-系统分析师-备考笔记

根据学习视频和一些资料整理的软考系统分析师考试笔记,2025年下半年通关

提子同学是我 1027

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Django框架整理

Django是一个功能强大的web框架。 前言:框架模式简介 1、MVC和MTV框架模式:分层级进行管理 说到框架模式我们有必要简单的说下设计模式,了解下设计模式这个概念,因为有人对设计模式和框架模式的概念经常混淆 设计模式: 是一套被反复使用,多数人知道并经过分类的代码设计经验总结,是为了解决一些通用性问题的 目的:重用代码并保证代码的可靠性 设计模式分类:单例,抽象工厂 等等 23种模式 一句话总结:解

有用的话关个注,点个赞,收个藏🫶。 1713

Python __slots__ 内存优化:减少30%以上对象内存占用

Python对象默认使用__dict__字典存储属性,导致每个实例产生显著内存开销;__slots__通过编译期固定属性名,消除动态字典结构,将对象内存布局压缩为紧凑的C风格结构体。其核心价值在于降低单实例内存(如从64B降至40B)、提升CPU缓存命中率,并在海量实例场景(如行情快照、订单模型)中实现指数级内存节省。适用于字段固定、生命周期长、数量庞大的数据类,尤其配合dataclasses.slots=True可兼顾类型安全与工程效率。

wyjvip333的专栏 465

Python异常类型设计:从错误处理到契约建模

在Python中,异常不仅是运行时错误的信号,更是程序逻辑中可编程、可分类、可追溯的第一类公民。其本质是类型系统在错误场景下的延伸——通过继承`Exception`及其分层体系(如`ValueError`、`OSError`、`LookupError`),实现错误语义的精准表达与结构化处理。这种类型化设计支撑了可观测性建设、智能重试、链式诊断等关键工程能力,显著提升故障定位效率与API健壮性。真实项目中,合理选用标准异常或自定义类型(如`BusinessRuleViolationError`),配合`rai

weixin_30591551的博客 370

Python底层原理:字节码、对象模型与内存管理深度解析

Python作为解释型语言,其运行本质由CPython解释器驱动,核心在于字节码执行、对象内存布局和动态作用域机制。理解`dis`反编译出的字节码指令(如`LOAD_FAST`、`BINARY_ADD`),能揭示语法糖背后的性能差异;掌握`PyObject_HEAD`、引用计数与`__slots__`等对象模型细节,是优化内存占用与避免隐式拷贝的关键;而LEGB作用域规则与闭包中`cell`对象的行为,则直接决定变量生命周期与线程安全。这些底层原理支撑着pandas链式操作、asyncio并发模型、Pyod

WGH100817的博客 339

SUMTEC:轻量级博客嵌入式组件协议解析

SUMTEC是一种面向静态博客的微型嵌入式组件协议,其核心是通过语义化HTML标签(如<sumtec>)声明式集成可执行逻辑单元。它基于数据契约(data-sumtec-*属性)、沙盒隔离(iframe/Web Worker)与执行模式分层(client/server/hybrid)三大原理,实现内容与逻辑彻底解耦。技术价值在于零构建依赖、天然安全边界、跨语言协同能力(WASM/Python/Rust),显著降低交互式内容的嵌入门槛。典型应用场景包括技术博客中的代码运行器、算法可视化、实时数据展示及教育类可

unixboy 491

软考——架构师笔记

该文章可作为系统架构设计师考试的参考笔记。

weixin_43930239的博客 705

【数据结构】基于比较的排序算法 - 交换排序

本文介绍交换排序中的冒泡排序与快速排序。冒泡排序通过相邻元素比较交换,实现升序,时间复杂度最坏为O(N²),空间复杂度O(1),稳定且适合小规模有序数据。快速排序采用分治思想,以基准值划分区间,平均时间复杂度O(N log N),空间复杂度O(log N),但不稳定,实际应用中性能优异,可通过随机基准、小区间优化等提升效率。

careathers的博客 373

【数据结构-5】单链表的实现

单链表,具体来说是单向的、不带头的、不循环的链表。链表由一个一个节点组成,每个节点分为数据域和指针域,数据域存放数据,指针域存放下一节点的地址。这样,就可以根据指针域中的地址找到下一个节点,节点就串起来了构成了单链表。

a bit 210

C# 数据结构和特殊类型

.NET Core(现称.NET)提供丰富数据结构,优化性能与开发效率。日常开发首选List<T>和Dictionary<TKey,TValue>;高性能场景推荐Span<T>与Memory<T>减少内存分配;并发环境使用ConcurrentDictionary等线程安全集合;避免非泛型集合如ArrayList。

cccloveforever的博客 721

pandas 深度入门:从数据结构到一份真实销售报表

本文系统讲解Pandas核心应用,从三分钟安装到完整月度报表生成,涵盖数据读取、清洗、筛选、分组聚合、表连接、透视表与时间序列等13个关键环节。强调“先看数据再动手”,掌握Series/DataFrame/Index结构本质,熟练运用loc/iloc、merge校验、agg/transform区别,通过真实案例实现高效报表自动化,告别手动Excel操作。最后提供性能优化与高频报错解决方案,助力读者快速上手,真正实现“写二十行代码,跑三秒出结果”。

信息安全领域优质创作者|操作系统领域专家 310
上一篇: 深入探索CORBA对象生命周期之慨述-Java基础-Java-编程开发
下一篇: Java咖啡馆(2)——第一杯咖啡-Java基础-Java-编程开发
java169
博客等级 码龄19年 27粉丝 2568原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值