设计模式15-门面模式

news2024/11/26 4:53:39

设计模式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.coloradmin.cn/o/1962450.html

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

相关文章

分布式日志分析系统--ELK

文章目录 ELK概述ELK主要特点ELK应用架构 Elasticsearch原理JSON格式倒排索引 ES与关系型数据库ES相关概念ES安装说明1.环境初始化2.优化系统资源限制配置3.编辑ES服务文件elasticsearch. yml 优化ELK集群安装脚本scp的使用集群安装成功 Shell命令API使用创建索引创建Type创建分…

yocto系列讲解[实战篇]95 - 使用外部第三方交叉编译器toolchain

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 概述下载toolchain包部署toolchain下载yocto下载toolchain layer添加toolchain layer配置toolchain变量编译和测试验证返回总目录:Yo…

中控屏UI设计全解析:布局与交互技巧

在现代科技的浪潮中&#xff0c;中控屏已成为智能系统不可或缺的交互界面。无论是智能家居、车载系统还是工业控制&#xff0c;一个直观、易用且美观的中控屏 UI 设计对于提升用户体验至关重要。本教程将带领你深入探索中控屏UI设计的精髓&#xff0c;指导你如何打造出既专业又…

一些Kafka面试题

Kafka是如何保证消息不丢失&#xff1f; 1.生产者发送消息到Broker丢失&#xff1a; 设置异步发送&#xff1a;发送失败则使用回调进行记录或者重发 消息重试&#xff1a;参数配置&#xff0c;可以设置重试次数 2.消息在broker中存储丢失 发送确认机制acks acks0&#xf…

创新突破 | OpenCSG发布StarShip CodeReview v1.0.0 Beta版

1. 代码审查很关键但耗时耗力 在软件开发过程中&#xff0c;代码审查是确保代码质量的关键环节。代码审查有助于维护代码标准和发现潜在错误&#xff0c;但也常常耗费大量时间和精力。审查者不仅需要深入理解代码逻辑&#xff0c;还要在繁复的逻辑中识别Bug&#xff0c;这个过…

如何使用 Odoo 16 主生产调度程序规划生产

为了优化运营并提高生产力&#xff0c;企业需要生产管理软件。在当今竞争激烈的经济环境中&#xff0c;有效的资源管理对企业至关重要。为制造业务设计的软件经常用于控制收入增长和盈利能力。ERP&#xff08;企业资源规划&#xff09;系统是专门为制造业创建的&#xff0c;可以…

Java刷题: 丑数判断

题目 丑数 就是只包含质因数 2、3 和 5 的正整数。 给你一个整数 n &#xff0c;请你判断 n 是否为 丑数 。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 解题思路 我觉得刷题是为了扩宽思考的广度。看到这题的时候&#xff0c;我的大脑是发懵的…

技术成神之路:设计模式(十)备忘录模式

介绍 备忘录模式&#xff08;Memento Pattern&#xff09;是一种行为设计模式&#xff0c;它允许在不破坏封装性的前提下捕获和恢复对象的内部状态。通过备忘录模式&#xff0c;可以在程序运行过程中保存和恢复对象的某个状态&#xff0c;从而实现“撤销”等功能。 1.定义 备忘…

11 优化器

目录 1. 随机梯度下降系优化器&#xff1a;SGD 1.1 算法种类 1.2 优缺点 2 SGDM 即为SGD with momentum 动量 2.1 公式 2.2 动量的优缺点 优点 缺点 2.3 使用场景 3 AdaGrad 3.1 公式 3.2 AdaGrad的优缺点 优点 缺点 3.3 使用场景 3.4 Adam 3.4.1 Adam优化器的…

倒计时:60秒后再输入验证码

思路1&#xff1a;每隔 1 秒种减 1 &#xff0c;直到减到 0 为止。可以写成公用方法。亲测有效。 countDown(){ const TIME_COUNT 60; if (!this.timer) { this.count TIME_COUNT; this.codeShow false; this.timer setInterval(() > { if (this.count > 0 &&…

苹果密码解锁工具已注册专业版_不限制电脑

Aiseesoft iPhone Unlocker&#xff1a;轻松解锁iPhone。功能强大&#xff1a;一键移除4位、6位密码、Touch ID和Face ID。隐私保护&#xff1a;创建密码&#xff0c;安全无忧。数据提醒&#xff1a;解锁时&#xff0c;注意数据和设置将被清除。Apple ID 解锁&#xff1a;快速删…

【Spring Boot教程:从入门到精通】掌握Spring Boot开发技巧与窍门(三)-配置git环境和项目创建

主要介绍了如何创建一个Springboot项目以及运行Springboot项目访问内部的html页面&#xff01;&#xff01;&#xff01; 文章目录 前言 配置git环境 创建项目 ​编辑 在SpringBoot中解决跨域问题 配置Vue 安装Nodejs 安装vue/cli 启动vue自带的图形化项目管理界面 总结 前言 …

Qt基础 | TCP通信 | TCP服务端与客户端程序设计 | QTcpServer | QTcpSocket

文章目录 一、TCP 通信1.TCP 通信概述2.TCP 服务器端程序设计2.1 主窗口定义与构造函数2.2 网络监听与 socket 连接的建立2.3 与 TCP 客户端进行数据通信 3.TCP 客户端程序设计3.1 主窗口定义与构造函数3.2 与服务器端建立 socket 连接3.3 与 TCPServer 的数据收发 4.小结 Qt 网…

[Docker][Docker Image]详细讲解

目录 1.Docker镜像是什么&#xff1f;2.Docker镜像加载原理1.bootfs2.rootfs3.为什么CentOS镜像几个G&#xff0c;而Docker CentOS镜像才几百M&#xff1f;1.CentOS2.Docker CentOS 3.镜像分层1.Union FS2.分层理解3.容器层 vs 镜像层 4.镜像命令1.docker images2.docker image…

大数据信用报告查询会不会留下查询记录?怎么选择查询平台?

最近有不少网友都在咨询一个问题&#xff0c;那就是大数据信用报告查询会不会留下查询记录&#xff0c;会不会对自己的征信产生影响&#xff0c;下面本文就详细为大家介绍一下&#xff0c;希望对你了解大数据信用有帮助。 首先、大数据信用与人行征信是独立的 很多人只知道人行…

innovus:如何only select highlighted

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 来自星球提问&#xff1b; 1&#xff09;ICC2 2&#xff09;innovus View->Set Preference&#xff0c;勾选Only Select Highlighted

新装centos7虚拟机如何配置网络,NAT配置固定IP

首先声明&#xff0c;我想使用的是NAT连接模式&#xff0c;并且设置完IP之后&#xff0c;使得这个IP固定住&#xff0c;以后不会再变了。 文章目录 1&#xff0c;打开Vmware软件的【编辑】-【虚拟网络编辑器】2&#xff0c;先选择VMnet8&#xff08;画1处&#xff09;&#xf…

2025上海国际显示技术及应用创展览会

DIC EXPO2025中国&#xff08;上海&#xff09;国际显示技术及应用创展览会 时间&#xff1a;2025年8月7-9日 地点&#xff1a;上海新国际博览中心 主办单位&#xff1a; 中国光学光电子行业协会液晶分会 联合主办&#xff1a; 中国电子材料行业协会 中国电子商会 韩国…

嵌入式人工智能(32-基于树莓派4B的旋转编码器-EnCoder11)

1、旋转编码器 旋转编码器是一种输入设备&#xff0c;通常用于测量和控制旋转运动。它由一个旋转轴和一系列编码器组成。旋转编码器可以根据旋转轴的位置和方向来测量旋转角度&#xff0c;并将其转化为电子信号输出。 旋转编码器通常分为两种类型&#xff1a;绝对值编码器和增…

【微服务】Spring Cloud Gateway

文章目录 强烈推荐引言主要功能关键概念示例配置依赖添加常见的几种整合案例1. 与 Spring Cloud Eureka 整合2. 与 Spring Cloud Config 整合3. 与 Spring Cloud Sleuth 和 Zipkin 整合4. 与 Spring Cloud Security 整合5. 与 Resilience4j 整合6. 与 Redis 整合 结论强烈推荐专…