设计模式15-门面模式

设计模式15-门面模式

  • "接口隔离"模式
    • 典型模式
      • 1. 适配器模式(Adapter Pattern)
      • 2. 装饰模式(Decorator Pattern)
      • 3. 桥接模式(Bridge Pattern)
      • 4. 代理模式(Proxy Pattern)
      • 5. 策略模式(Strategy Pattern)
      • 总结
  • 推导
    • A方案
    • B方案
  • 定义
  • 结构
    • 主要元素解释
    • 示意图的整体解释
  • 要点总结

"接口隔离"模式

组建构建过程中某些接口之间直接的依赖往往会带来许多问题。甚至根本无法实现。采用添加一层间接稳定的接口的方式来隔离。本来互相紧密关联的接口是一种常见的解决方式。

典型模式

接口隔离原则(Interface Segregation Principle, ISP)是面向对象设计中的一个重要原则。它强调不应强迫客户端依赖于他们不需要的方法,而应将接口拆分成更小和更具体的接口,使得客户端只需知道它们需要的方法。

在实际的软件设计中,有几个设计模式能够帮助实现接口隔离原则:

1. 适配器模式(Adapter Pattern)

动机: 将一个接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。

实现:

  • 类适配器模式:通过多重继承实现,适配器继承自适配者类和目标接口。
  • 对象适配器模式:通过组合实现,适配器持有适配者对象的实例。

代码示例:

class ITarget {
public:virtual void request() = 0;
};class Adaptee {
public:void specificRequest() {std::cout << "Adaptee specific request." << std::endl;}
};class Adapter : public ITarget {
private:Adaptee* adaptee;public:Adapter(Adaptee* adaptee) : adaptee(adaptee) {}void request() override {adaptee->specificRequest();}
};

2. 装饰模式(Decorator Pattern)

动机: 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式相比生成子类更为灵活。

实现:

  • 使用一个抽象接口和具体的装饰类,这些装饰类可以在运行时动态地添加行为到对象中。

代码示例:

class Component {
public:virtual void operation() = 0;
};class ConcreteComponent : public Component {
public:void operation() override {std::cout << "ConcreteComponent operation." << std::endl;}
};class Decorator : public Component {
protected:Component* component;public:Decorator(Component* component) : component(component) {}void operation() override {component->operation();}
};class ConcreteDecorator : public Decorator {
public:ConcreteDecorator(Component* component) : Decorator(component) {}void operation() override {Decorator::operation();std::cout << "ConcreteDecorator additional operation." << std::endl;}
};

3. 桥接模式(Bridge Pattern)

动机: 将抽象部分与它的实现部分分离,使它们都可以独立地变化。

实现:

  • 抽象类和实现类通过桥接模式分离开来,可以独立地对其进行扩展和变化。

代码示例:

class Implementor {
public:virtual void operationImpl() = 0;
};class ConcreteImplementorA : public Implementor {
public:void operationImpl() override {std::cout << "ConcreteImplementorA operation." << std::endl;}
};class Abstraction {
protected:Implementor* implementor;public:Abstraction(Implementor* implementor) : implementor(implementor) {}virtual void operation() {implementor->operationImpl();}
};class RefinedAbstraction : public Abstraction {
public:RefinedAbstraction(Implementor* implementor) : Abstraction(implementor) {}void operation() override {implementor->operationImpl();}
};

4. 代理模式(Proxy Pattern)

动机: 为其他对象提供一种代理以控制对这个对象的访问。

实现:

  • 使用代理类来控制对实际对象的访问,代理类实现了实际对象的接口。

代码示例:

class Subject {
public:virtual void request() = 0;
};class RealSubject : public Subject {
public:void request() override {std::cout << "RealSubject request." << std::endl;}
};class Proxy : public Subject {
private:RealSubject* realSubject;public:Proxy(RealSubject* realSubject) : realSubject(realSubject) {}void request() override {if (realSubject == nullptr) {realSubject = new RealSubject();}realSubject->request();}
};

5. 策略模式(Strategy Pattern)

动机: 定义一系列算法,并将它们封装起来,使它们可以相互替换,本模式使得算法可独立于使用它的客户而变化。

实现:

  • 定义一个策略接口和具体的策略实现类,客户端通过组合的方式使用策略接口来实现不同的行为。

代码示例:

class Strategy {
public:virtual void algorithm() = 0;
};class ConcreteStrategyA : public Strategy {
public:void algorithm() override {std::cout << "ConcreteStrategyA algorithm." << std::endl;}
};class ConcreteStrategyB : public Strategy {
public:void algorithm() override {std::cout << "ConcreteStrategyB algorithm." << std::endl;}
};class Context {
private:Strategy* strategy;public:Context(Strategy* strategy) : strategy(strategy) {}void setStrategy(Strategy* strategy) {this->strategy = strategy;}void executeAlgorithm() {strategy->algorithm();}
};

总结

接口隔离原则强调将大接口拆分成更小的、更加具体的接口,以便客户端只依赖于它们实际需要的接口。上述设计模式在一定程度上体现了这一原则,通过这些模式的合理运用,可以设计出更加灵活和可维护的系统。

推导

在这里插入图片描述这张图展示了系统设计中关于系统间耦合复杂度减少的一种对比方案。具体来说,图中分为A方案和B方案两种系统设计方案,通过这两种方案的对比,阐述了如何通过设计模式(特别是Facade模式)来降低系统间的耦合复杂度,从而提高系统的可维护性和可扩展性。

A方案

描述:
在A方案中,客户端类(client classes)与子系统类(subsystem classes)之间存在直接耦合。这意味着客户端类直接依赖于多个子系统类,这种直接依赖关系增加了系统的耦合度,使得系统变得复杂且难以维护。当子系统发生变化时,客户端类也需要进行相应的修改,这违反了开闭原则(软件实体应当对扩展开放,对修改关闭)。
问题:
直接耦合导致系统结构紧密,修改成本高,且不利于系统的扩展和维护。

B方案

描述:

  • 为了解决A方案中的问题,B方案引入了Facade模式。Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。在B方案中,Facade作为客户端类和子系统类之间的中介,客户端类不再直接与子系统类交互,而是通过Facade来进行交互。这样,客户端类与子系统类之间的耦合度大大降低,客户端类只需与Facade交互即可,无需了解子系统类的内部细节。

优势:

  • Facade模式降低了系统的耦合度,提高了系统的灵活性和可维护性。当子系统内部发生变化时,客户端类无需修改,只需调整Facade即可,从而降低了修改成本和风险。

定义

为此系统中的一组接口提供了一个一致稳定的界面。门面模式是定义了一个高层接口,这个接口使得这一子系统更容易的使用和复用。

结构

在这里插入图片描述

这张门面模式(Facade Pattern)结构示意图清晰地展示了该设计模式在软件架构中的应用。门面模式是一种结构型设计模式,它为子系统中的一组接口提供一个统一的接口,使得这一子系统更加容易使用。在这个示意图中,各个元素和它们之间的关系被巧妙地描绘出来,以便理解门面模式的工作原理。

主要元素解释

结构(Structure):

  • 这个词在图中可能指代整个软件系统的结构,特别是与门面模式相关的那部分结构。它强调了系统内部的组织和关系,尤其是门面如何作为这些内部结构的对外接口。

Facade:

  • 门面是此设计模式的核心。在图中,Facade被明确标出,作为子系统(subsystem classes)与客户端(未直接显示在图中)之间的中介。门面类为子系统提供了一个简化的接口,客户端通过这个接口与子系统交互,而无需直接与子系统中的多个类打交道。这样做的好处是降低了系统的耦合度,提高了系统的可维护性和可扩展性。

子系统类(subsystem classes):

  • 这些是系统中实际执行功能的类。在图中,虽然文本“suhsysiem ciasses”似乎是“subsystem classes”的拼写错误,但我们可以推断出它指的是多个子系统类。这些类之间可能存在复杂的依赖和交互关系,但通过使用门面模式,这些复杂性被封装在子系统内部,对外部客户端透明。

示意图的整体解释

整个示意图通过简洁的线条和清晰的标签,展示了门面模式在软件系统中的应用。客户端(尽管未在图中直接显示)通过门面与子系统交互,而不需要知道子系统内部的具体实现细节。这种设计使得系统更加模块化,易于管理和维护。同时,它也使得系统更加灵活,因为当子系统内部发生变化时,只要门面接口保持不变,客户端代码就无需修改。

综上所述,这张门面模式结构示意图通过直观的方式展示了该设计模式在软件架构中的关键作用,即提供一个简化的接口来封装子系统的复杂性。系统的复杂性。

要点总结

  • 从客户程序的角度来看,门面模式简化了一个组件系统的接口。组建内部与外部客户程序来说,达到了一种解耦的效果。内部子系统的任何变化都不会影响到门面模式接口的变化。
  • 平面设计模式更注重从架构的层次去看整个系统,而不是单个类的层次。美面膜是很多时候更是一种架构设计模式。
  • 平面设计模式并非一个集装箱可以任意的放进任何多个对象门面模式中组建的内部应该是相互和关系比较大的系列组件,而不是一个简单的功能集合。

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

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

相关文章

Git基本原理介绍及常用指令

文章目录 前言一、Git是什么&#xff1f;集中化的版本控制系统分布式版本控制系统 二、Git基本概念三、git命令操作配置用户信息常用指令 总结 前言 如果你用Microsoft Word写过论文&#xff0c;那你一定有这样的经历&#xff1a;想删除一个段落&#xff0c;又怕将来想恢复找不…

linux:用户管理,增删改

1.查看当前登录的用户信息 [root@bgx ~]# id #查看当前所登陆的用户信息 # uid:用户id,系统只能识别uid,不能识别名字,人看名字 # gid:组id uid=0(root) gid=0(root) groups=0(root) [root@bgx ~]# id oldboy #查看其它用户的信息 uid=1000(oldboy) gid=1000(oldboy) g…

【Linux】2.Linux 指令大揭秘:常见八个指令的妙用(上)

欢迎来到 CILMY23 的博客 &#x1f3c6;本篇主题为&#xff1a;Linux 指令大揭秘&#xff1a;常见八个指令的妙用&#xff08;上&#xff09; &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | …

千万别从系统中创建线程, 看看从线程池中调用的线程的效率(1)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

Web3.js 4.x版本事件监听详解:从HTTP到WebSocket的迁移

项目场景 在一个使用以太坊区块链技术的项目中&#xff0c;需要监听智能合约的事件&#xff0c;以便在事件触发时能够及时响应。项目中使用了web3.js库的4.x版本&#xff0c;节点使用Geth启动&#xff0c;并通过HTTP与节点进行通信。 问题描述 合约DataStorage.sol文件已经定…

学习c语言第16天(数据的存储)

一、数据类型的介绍 c语言基本的内置类型 类型的意义&#xff1a; 1.使用这个类型开辟内存空间的大小(大小决定了使用范围) 2.如何看待内存空间的视角 1.类型的基本归类 整形家族 字符的本质是ASCII码值&#xff0c;是整形 int a等于 signed int a char稍微特殊一些…

新书速览|动手学PyTorch建模与应用:从深度学习到大模型

《动手学PyTorch建模与应用&#xff1a;从深度学习到大模型》 本书内容 《动手学PyTorch建模与应用:从深度学习到大模型》是一本从零基础上手深度学习和大模型的PyTorch实战指南。《动手学PyTorch建模与应用:从深度学习到大模型》共11章&#xff0c;第1章主要介绍深度学习的概念…

Python --Pandas库基础方法(2)

文章目录 Pandas 变量类型的转换查看各列数据类型改变数据类型 重置索引删除行索引和切片seriesDataFrame取列按行列索引选择loc与iloc获取 isin()选择query()的使用排序用索引排序使用变量值排序 修改替换变量值对应数值的替换 数据分组基于拆分进行筛选 分组汇总引用自定义函…

优思学院|抽样检验的概念和21种抽样方式

抽样检验的概念 根据事先制定的抽样方案&#xff0c;从一批产品中随机抽取一部分作为样品&#xff0c;以这部分样品的检验结果&#xff0c;对整批产品质量合格与否作出判定的活动过程&#xff0c;称为抽样检验。除了用于质量控制之外&#xff0c;抽样检验同样适用于在六西格玛…

AI工作流程设计的自动化优化:微软与斯坦福的新成果 - Trace

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

学习网络安全 为什么Linux首择Kali Linux? 以及如何正确的使用Kali Linux

1.什么是kali linux&#xff1f; Kali Linux是一款基于Debian的Linux发行版&#xff0c;主要用于网络安全测试和渗透测试。它由全球顶尖的安全专家和黑客社区维护开发&#xff0c;提供了丰富的工具和资源&#xff0c;用于测试安全性、漏洞利用和渗透测试。此外&#xff0c;Kal…

修复msvcp120.dll丢失的问题的几种简单方法,msvcp120.dll是什么

在使用电脑时&#xff0c;你可能会遭遇一个提示称“msvcp120.dll丢失”的错误信息。这个问题比较普遍&#xff0c;主要是因为你的系统中缺失了某个特定的动态链接库&#xff08;DLL&#xff09;文件。msvcp120.dll是由 Microsoft Visual C 可再发行包提供的关键文件&#xff0c…

一键切换阿里yum源(包括其他系统repo镜像查找方法)

一键切换阿里yum源 示例命令其他系统repo镜像GitHub文档 示例命令 # 备份旧源 mv CentOS-Base.repo CentOS-Base.repo.bak # 添加新源(阿里镜像源) wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo其他系统repo镜像 这里的示例是用…

链表篇-02.从尾到头打印链表(反转链表)

解题思路&#xff1a; 链表从尾到头打印链表, 我的思路是 用三个指针,第一个指针(pre)指向指向头节点的前一个位置&#xff0c;第二个指针(cur)指向头节点&#xff0c; 然后依次往后执行&#xff0c;第三个指针用于临时记录第二个指针的下一个位置。 代码详情: import java.…

2024年中职云计算实验室建设及云计算实训平台整体解决方案

随着信息技术的飞速发展&#xff0c;云计算作为新一代信息技术的核心&#xff0c;正逐步渗透到各行各业&#xff0c;成为推动数字化转型的重要力量。为了适应这一趋势&#xff0c;中职教育作为技能型人才培养的重要阵地&#xff0c;亟需加强云计算实验室建设与云计算实训平台的…

【Linux】CentOS更换国内阿里云yum源(超详细)

目录 1. 前言2. 打开终端3. 确保虚拟机已经联网4. 备份现有yum配置文件5. 下载阿里云yum源6. 清理缓存7. 重新生成缓存8. 测试安装gcc 1. 前言 有些同学在安装完CentOS操作系统后&#xff0c;在系统内安装比如&#xff1a;gcc等软件的时候出现这种情况&#xff1a;&#xff08…

【C++进阶学习】第九弹——哈希的原理与实现——开放寻址法的讲解

前言&#xff1a; 在前面&#xff0c;我们已经学习了很多存储机构&#xff0c;包括线性存储、树性存储等&#xff0c;并学习了多种拓展结构&#xff0c;效率也越来越高&#xff0c;但是是否有一种存储结构可以在大部分问题中都一次找到目标值呢&#xff1f;哈希可能能实现 目录…

Maven已经导入Junit包,但是还是无法使用注解

Maven已经导入Junit包&#xff0c;但是还是无法使用注解 背景&#xff1a; 导入了Junit的依赖 <dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></d…

【初阶数据结构题目】2.移除元素

文章目录 顺序表算法题代码&#xff1a; 顺序表算法题 点击链接做题 移除元素 思路&#xff1a;定义两个变量指向数组第一个位置&#xff0c;判断nums[src]是否等于val 相等&#xff0c;src不相等&#xff0c;nums[dst] nums[src],src,dst 代码&#xff1a; int removeElem…

如何使用CANoe自带的TCP/IP Stack验证TCP的零窗口探测机制

如果想利用CANoe自带的TCP/IP协议栈验证TCP的零窗口探测机制,就必须添加一个网络节点并配置独立的CANoe TCP/IP协议栈,作为验证对象。而与它进行TCP通信的对端也是一个网络节点,但不要配置TCP/IP协议栈,而是使用CAPL代码在底层组装TCP报文模拟TCP通信过程。这样可以尽量减少…