【封装那些事】 缺失封装

news2025/1/10 10:16:43

缺失封装

没有将实现变化封装在抽象和层次结构中时,将导致这种坏味。

表现形式通常如下:

  • 客户程序与其需要的服务变种紧密耦合,每当需要支持新变种或修改既有变种时,都将影响客户程序。
  • 每当需要在层次结构中支持新变种时,都添加了大量不必要的类,这增加了设计的复杂度。

为什么不能缺失封装?

开闭原则(OCP)指出,类型应对扩展开放,对修改关闭。也就是说应该通过扩展(而不是修改)来改变类型的行为。没有在类型或层次结构中封装实现变化时,便违反了OCP。

缺失封装潜在的原因

未意识到关注点会不断变化

没有预测到关注点可能发生变化,进而没有在设计中正确封装这些关注点。

混合关注点

将彼此独立的各个关注点聚合在一个层次结构中,而不是分开时,如果关注点发生变化,可能导致类的数量呈爆炸式增长。

幼稚的设计决策

采用过于简单的方法,如为每种变化组合创建一个类时,可能导致设计无谓的复杂。

示例分析一

假设有一个Entryption类,它需要使用加密算法对数据进行加密。可供选择的加密算法有很多,包括DES(数据加密标准)、AES(高级加密标准)、TDES(三重数据加密标准)等。Entryption类使用DES算法对数据进行加密。

public class Encryption
{
    /// <summary>
    /// 使用DES算法进行加密
    /// </summary>
    public void Encrypt()
    {
        // 使用DES算法进行加密
    }
}

假设出现了新需求,要求使用AES算法对数据进行加密。

最差的方案出现了:

public class Encryption
{
    /// <summary>
    /// 使用DES算法进行加密
    /// </summary>
    public void EncryptUsingDES()
    {
        // 使用DES算法进行加密
    }

     /// <summary>
    /// 使用AES算法进行加密
    /// </summary>
    public void EncryptUsingAES()
    {
        // 使用AES算法进行加密
    }
}

这种方案有很多不尽如人意的地方:

  • Encryption类变得更大、更难以维护,因为它实现了多种加密算法,但是每次只使用一种。
  • 难以添加新算法以及修改既有算法,因为加密算法是Encryption类不可分割的部分。
  • 加密算法向Encryption类提供服务,但是与Encryption类紧紧耦合在一起,无法在其它地方重用。

不满意就重构,首先使用继承进行重构,会有2种方案可以选择:

选择1:

让Encryption类根据需求继承AESEncryptionAlgorithm或DESEncryptionAlgorithm类,并提供方法Encrypt()。这种方案带来的问题是Encryption类在编译阶段就将关联到特定的加密算法,更严重的是类之间的关系并不是is-a关系。

/// <summary>
/// AES算法加密类
/// </summary>
public class AESEncryptionAlgorithm
{
    /// <summary>
    /// 使用AES算法进行加密
    /// </summary>
    public void EncryptUsingAES()
    {
        // 使用AES算法进行加密
    }
}

/// <summary>
/// DES算法加密类
/// </summary>
public class DESEncryptionAlgorithm
{
    /// <summary>
    /// 使用DES算法进行加密
    /// </summary>
    public void EncryptUsingDES()
    {
        // 使用DES算法进行加密
    }
}

public class Encryption: AESEncryptionAlgorithm
{
    /// <summary>
    /// 使用算法进行加密
    /// </summary>
    public void Encrypt()
    {
        EncryptUsingAES();
    }
}

选择2:

创建子类AESEncryption和DESEncryption,它们都扩展了Encryption类,并分别包含加密算法AES和DES的实现。客户程序可创建Encryption的引用,这些引用指向特定子类的对象。通过添加新的子类,很容易支持新的加密算法。但是这种方案的问题是AESEncryption和DESEncryption将继承Encryption类的其它方法,降低了加密算法的可重用性。

public abstract class Encryption
{
    /// <summary>
    /// 使用算法进行加密
    /// </summary>
    public abstract void Encrypt();
}

/// <summary>
/// AES算法加密类
/// </summary>
public class AESEncryption : Encryption
{
    /// <summary>
    /// 使用 AES算法进行加密
    /// </summary>
    public override void Encrypt()
    {
        // 使用 AES算法进行加密
    }
}

/// <summary>
/// DES算法加密类
/// </summary>
public class DESEncryption : Encryption
{
    /// <summary>
    /// 使用 DES算法进行加密
    /// </summary>
    public override void Encrypt()
    {
        // 使用 DES算法进行加密
    }
}

最佳的选择是使用策略模式:

  • 可在运行阶段给Encryption对象配置特定的加密算法
  • 可在其它地方重用层次结构EncryptionAlgorithm中定义的算法
  • 很容易根据需要支持新的算法
/// <summary>
/// 算法加密接口
/// </summary>
public interface EncryptionAlgorithm
{
   void Encrypt();
}

/// <summary>
/// DES算法加密类
/// </summary>
public class DESEncryptionAlgorithm : EncryptionAlgorithm
{
    public void Encrypt()
    {
        //使用 DES算法进行加密
    }
}
/// <summary>
/// AES算法加密类
/// </summary>
public class AESEncryptionAlgorithm : EncryptionAlgorithm
{
    public void Encrypt()
    {
        //使用 AES算法进行加密
    }
}

public class Encryption
{
    private EncryptionAlgorithm algo;

    public Encryption(EncryptionAlgorithm algo)
    {
        this.algo = algo;
    }
 
    /// <summary>
    /// 使用算法进行加密
    /// </summary>
    public void Encrypt()
    {
        algo.Encrypt();
    }
}

示例分析二

支持使用不同算法(DES和AES)对各种内容(Image和Text)进行加密的设计。

最简单最直观的的设计:

在这个设计中,有两个变化点:支持的内容类型和加密算法类型。对于这两个变化点的每种可能组合,都使用了一个类来表示。这样会有一个严重的问题:假设现在要求支持新加密算法TDES和新内容类型Data,类的数量呈爆炸性增长。因为变化点混在了一起,没有分别进行封装。

使用桥接模式进行封装:

使用桥接模式,分别封装这两个关注点的变化。现在要引入新内容类型Data和新加密算法TDES,只需要添加两个新类。既解决了类数量呈爆炸增长的问题,又增加了根为接口EncryptionAlgorithm层次结构中的加密算法的可重用性。

总结

  1. 不相关的关注点混在一起,抽象将变得难以重用。
  2. 对业务中可能的变化点,要给予扩展点,保证开闭原则(OCP),对扩展开放,对修改关闭。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

港联证券投资前瞻:核电订单重回历史高位 C919圆满完成商业首航

上周五&#xff0c;沪指盘中弱势震荡下探&#xff0c;午后反弹拉升&#xff0c;科创50指数表现强势。截至收盘&#xff0c;沪指涨0.35%报3212.50点&#xff0c;深成指涨0.12%报10909.65点&#xff0c;创业板指跌0.66%报2229.27点&#xff0c;科创50指数涨1.66%&#xff1b;两市…

干货!详解playwright实现自动等待的原理

playwright在执行操作之前对元素执行一系列可操作性检查&#xff0c;以确保这些行动按预期运行。它会自动等待&#xff08;auto-wait&#xff09;所有相关检查通过&#xff0c;然后才执行请求的操作。如果所需的检查未在给定的范围内通过timeout&#xff0c;则操作将失败并显示…

vue项目中详情页向下滚动,导航选中;点击导航,详情页跳到指定区域

需求1&#xff1a;滚轮向下滚动的时候&#xff0c;导航选中 需求2&#xff1a;点击导航的时候&#xff0c;会跳转到目标区域 在生命周期中获取屏幕的高度 mounted() {//获取屏幕高度console.log(document.documentElement.clientHeight);//667}, 这里就考虑到项目优化防抖与…

2023年上半年软件设计师考试中级真题答案+解析(详细版)

目录 背景过程计算机组成原理产权保护结构化开发方法 总结 背景 2023年软考讲解 软考&#xff08;软件技术人员职业资格考试&#xff09;是中国的一项职业资格考试&#xff0c;主要针对软件行业从业人员。软考的主要目标是评估考生在软件开发、软件测试、软件项目管理等方面的…

音乐小白乐器选择,如何学一手才艺,推荐尤克里里

乐器难度说明 注意&#xff1a;这里的难度说明是音准的难度&#xff0c;就是能不能发出标准的声音 乐器按照演奏方式分类&#xff0c;分为 演奏方式乐器举例难度等级难度说明敲击木鱼&#xff0c;架子鼓&#xff0c;钢琴1敲击乐是音最准的&#xff0c;敲哪个地方就发什么音&…

MongoDB学习笔记三

目录 1.数据库增删 1.1数据库创建 1.2数据库删除 2.集合增删 2.1创建集合 2.2删除集合 3.文档增删改查 3.1查询文档 3.2创建文档 3.3删除文档 3.4更新/修改文档 1.数据库增删 1.1数据库创建 数据库创建语法格式&#xff1a; use DatabaseName 在mongodb中使用use与在m…

油猴配置教程

文章目录 目录 文章目录 前言 一. 安装油猴 二、使用步骤 三.安装插件 (ChatGPT) 四. 脚本推荐 前言 作者简介: zuiacsn 座右铭: 抱怨身处黑暗,不如提灯前行 内容介绍: 油猴 油猴&#xff08;Tampermonkey&#xff09;指的是一个流行的用户脚本管理器&#xff0c;它能使…

智能照明“暗潮涌动”

在技术持续升级、消费者观念发生转变等多方因素的共同影响下&#xff0c;与智能相关的设备销量逐渐走俏。能够为人们带来便捷、舒适的智能家居产品也逐渐走进千家万户&#xff0c;深入到人们的日常生活中。在此背景下&#xff0c;智能家居行业日渐火热&#xff0c;实现了飞速发…

SLMi331数明深力科带DESAT保护功能隔离驱动应用笔记

SLMi33X系列SLMi331数明深力科首款单通道带DESAT保护功能的IGBT/SiC隔离驱动器。内置快速去饱和(DESAT) 故障检测功能、米勒钳位功能、漏极开路故障反馈、软关断功能以及可选择的自恢复模式&#xff0c;兼容光耦隔离驱动器。 SLMi331的DESAT阈值为6.5V&#xff0c;其最大驱动电…

Facebook广告投放和海外品牌推广(KOL)哪个未来发展好一点?

在当今数字化时代&#xff0c;品牌推广和营销策略正不断演变和创新。在海外市场拓展和品牌推广方面&#xff0c;Facebook广告投放和海外品牌推广&#xff08;KOL&#xff09;已经成为两种备受关注的策略。 1.Facebook广告投放的优势&#xff1a; 广告定位精准&#xff1a;Faceb…

究诸经典,探寻大模型演变之踪迹

编者按&#xff1a;在仅仅五年的时间里&#xff0c;大语言模型、transformers几乎完全改变了自然语言处理领域。 为了便于快速、扎实、深入地学习大语言模型&#xff0c;本文整理一个简单的经典学术资料列表&#xff0c;供正在入门中的机器学习研究人员和开发者参考。 以下是译…

JAVA基础---集合

一、树结构 二叉树、二叉查找树、平衡二叉树、红黑树 1、数据结构遍历方式 1、前序遍历&#xff1a;当前节点、左子节点、右子节点 2、中序遍历&#xff1a;左子节点、当前节点、右子节点 3、后序遍历&#xff1a;左子节点、右子节点、当前节点 4、层序遍历&#xff1a;一层…

几个提高工作效率的 Python 自动化脚本,收藏!

在这个自动化时代&#xff0c;我们有很多重复无聊的工作要做。 想想这些你不再需要一次又一次地做的无聊的事情&#xff0c;让它自动化&#xff0c;让你的生活更轻松。 那么在本文中&#xff0c;我将向您介绍 10 个 Python 自动化脚本&#xff0c;以使你的工作更加自动化&#…

javaWeb ssh小提琴管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh小提琴管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S 模式开发。开发环境为TOMCAT7.0,…

TypeScript实现贪吃蛇游戏

TS实现贪吃蛇游戏 文章目录 TS实现贪吃蛇游戏[toc]1.项目效果2.项目梳理3.项目准备4.主体页面结构5.CSS样式6.TS逻辑6.1 食物逻辑6.2 蛇逻辑6.3 记分板逻辑6.4 游戏控制器逻辑6.5 程序入口ts 1.项目效果 项目体验 2.项目梳理 这个小游戏主要包括积分面板&#xff0c;食物&…

2023上半年软件设计师真题评析

2023年上半年软设是2018年改版后的一次考试&#xff0c;以下内容根据考完回忆结合网上暂时流传的真题(不保证完全正确)整理&#xff0c;主要侧重相关知识点罗列&#xff0c;少讲或不讲具体的答案&#xff0c;主要给自己的计算机基础查漏补缺&#xff0c;同时也希望对大家有帮助…

基于AI技术的APP外包开发流程

AI技术发展非常迅速&#xff0c;最近一年有了巨大的技术突破&#xff0c;一些专家认为可以基于现在的AI技术将APP再重做一遍&#xff0c;这无疑将给创业者带来巨大机会。今天和大家分享使用AI重做一个APP的步骤和注意事项&#xff0c;希望对大家有所帮助。 需要遵循以下步骤和注…

5601-RIO-MCM 消除Modbus网络上的通信错误

当端口配置为从端口时&#xff0c;此参数指定内部用作Holding的零地址或起点的数据库地址 寄存器&#xff08;16位整数&#xff09;数据。Modbus功能读取保持寄存器数据代码3命令&#xff08;读取保持寄存器&#xff09;和由功能代码6写入&#xff08;预设单寄存器&#xff09;…

《论文阅读》在跨语料库上利用集成提示完成零样本的文本情感分类 COLING2022

《论文阅读》在跨语料库上利用集成提示完成零样本的文本情感分类 COLING2022 前言相关知识hubness problem零样本学习灵感来源验证点零样本情感分类的自然语言推理情感提示情感集成自我总结问题前言 你是否也对于理解论文存在困惑? 你是否也像我之前搜索论文解读,得到只是中…

【自然语言处理】- 作业6: 面向新冠肺炎的社会计算应用

课程链接: 清华大学驭风计划 代码仓库&#xff1a;Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的&#xff0c;其分为四门课&#xff0c;包括: 机器学习(张敏教授) &#xff0c; 深度学习(胡晓林教授), 计算…