当前位置: 首页 > news >正文

设计模式—外观模式(Facade)

目录

一、什么是外观模式?

二、外观模式具有什么优点吗?

三、外观模式具有什么缺点呢?

四、什么时候使用外观模式?

五、代码展示

①、股民炒股代码

②、投资基金代码

③外观模式


思维导图

 

一、什么是外观模式?

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

Facade:外观,为多个子系统对外提供一个共同的接口

SubSystem:子系统:实现子系统功能,每一个类表示为一个子系统

Client:客户,通过外观访问各个子系统功能

二、外观模式具有什么优点吗?

降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类;

三、外观模式具有什么缺点呢?

1.不能很好地限制客户使用子系统类,很容易带来未知风险;

2.增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”

四、什么时候使用外观模式?

①、在设计初期阶段,应该要有意识的将不同的两个层分离,比如经典的三层架构,就需要考虑在数据访问层和业务逻辑层、业务逻辑层和表示层的层与层之间建立外观的Facade,这样可以为复杂的子系统提供一个简单的接口,使得耦合大大降低。

②、在开发阶段,子系统往往因为不断地重构演化而变得越来越复杂,大多数的模式使得使用时也都会产生很多很小的类,这本是好事,但也给外部调用它们的用户程序带来了使用上的困难,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖。

③、在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须要依赖于它。


五、代码展示

场景:越来越多的人都在炒股票,行情很火, 但许多人进入这个行业只是盲目跟风,并不是足够了解证券知识,对于这个行业并不熟悉。如果是你自己单独去买股票的话需要了解每支股票具体的细节,如果要买十股的话就需要了解是个,这样非常麻烦。这个时候你就会想如果有一个帮手来帮助你管理股票的话就好了!基金就可以作为你的帮手,它把投资者分散的资金集中起来,交给专业的经理人进行管理,投资于股票、债券、外汇等领域,而基金投资的收益归持有投资者所有,管理机构只是收取一定比例的托管管理费用。你不需要了解股票具体是什么时候买和卖合适,你只需要把钱给基金,基金帮你买了这十股。

①、股民炒股代码

股票类

//股票1
class Stock1
{//卖股票public void Sell(){Console.WriteLine(" 股票1卖出");}//买股票public void Buy(){Console.WriteLine(" 股票1买入");}
}//股票2
class Stock2
{//卖股票public void Sell(){Console.WriteLine(" 股票2卖出");}//买股票public void Buy(){Console.WriteLine(" 股票2买入");}
}// 股票3
class Stock3
{//卖股票public void Sell(){Console.WriteLine(" 股票3卖出");}//买股票public void Buy(){Console.WriteLine(" 股票3买入");}
}//国债1
class NationalDebt1
{//卖股票public void Sell(){Console.WriteLine(" 国债1卖出");}//买股票public void Buy(){Console.WriteLine(" 国债1买入");}
}// 房地产1
class Realty1
{//卖股票public void Sell(){Console.WriteLine(" 房地产1卖出");}//买股票public void Buy(){Console.WriteLine(" 房地产1买入");}
}

客户端

static void Main(string[] args)
{Stock1 gu1 = new Stock1();       //关联关系:Stock1 gu1 =null; gu1 = new Stock1();Stock2 gu2 = new Stock2();Stock3 gu3 = new Stock3();NationalDebt1 nd1 = new NationalDebt1();Realty1 rt1 = new Realty1();gu1.Buy();gu2.Buy();gu3.Buy();nd1.Buy();rt1.Buy();gu1.Sell();gu2.Sell();gu3.Sell();nd1.Sell();rt1.Sell();Console.ReadKey();
}

这样的话用户需要了解股票、国债、房产情况,需要参与这些项目的具体买和卖。耦合性很高。我们可以增加基金类。

②、投资基金代码

基金类

//基金类
class Fund
{//成员变量Stock1 gu1;Stock2 gu2;Stock3 gu3;NationalDebt1 nd1;Realty1 rt1;//基金类,它需要了解所有的股票或其他投资方式的方法或属性,进行组合,以备外界调用//此处同原型模式有异曲同工之处,在实例化本类的同时实例化相应的子类public Fund()              //构造方法{gu1 = new Stock1();         //实例化股票1gu2 = new Stock2();         //实例化股票2gu3 = new Stock3();         //实例化股票3nd1 = new NationalDebt1();  //实例化国债1rt1 = new Realty1();        //实例化房地产1}public void BuyFund()        //买{gu1.Buy();gu2.Buy();gu3.Buy();nd1.Buy();rt1.Buy();}public void SellFund()          //卖{gu1.Sell();gu2.Sell();gu3.Sell();nd1.Sell();rt1.Sell();}
}//股票1
class Stock1
{//卖股票public void Sell(){Console.WriteLine(" 股票1卖出");}//买股票public void Buy(){Console.WriteLine(" 股票1买入");}
}//股票2
class Stock2
{//卖股票public void Sell(){Console.WriteLine(" 股票2卖出");}//买股票public void Buy(){Console.WriteLine(" 股票2买入");}
}//股票3
class Stock3
{//卖股票public void Sell(){Console.WriteLine(" 股票3卖出");}//买股票public void Buy(){Console.WriteLine(" 股票3买入");}
}//国债1
class NationalDebt1
{//卖股票public void Sell(){Console.WriteLine(" 国债1卖出");}//买股票public void Buy(){Console.WriteLine(" 国债1买入");}
}房地产1
class Realty1
{//卖股票public void Sell(){Console.WriteLine(" 房地产1卖出");}//买股票public void Buy(){Console.WriteLine(" 房地产1买入");}
}

客户端

static void Main(string[] args)
{ Fund jijin = new Fund();   //实例化基金类jijin.BuyFund();           //调用买的方法jijin.SellFund();           //调用卖的方法//此时用户不需要了解股票,甚至可以对股票一无所知,买了基金就回家睡觉//一段时间后再赎回就可以大把数钱。Console.ReadKey();          //等待用户按下任意键退出
}

这样写的好处是什么?外部不需要知道基金怎么组合的、具体细节,这样就大大降低应用程序复杂度,提高程序可维护性

与其它模式的联系:

基金类中的构造方法和原型模式很类似,客户端在实例化原型对象的时候,同时实例化具体的原型类

基金类中的买和卖的方法和建造者模式中的指挥者类的思想异曲同工之处,客户端提出要建造一个瘦人类告诉指挥者,指挥者指挥工人建造出小人,最后把建造好的小人展示给客户。

③外观模式

//四个子系统类
class SubSystemOne
{public void MethodOne(){Console.WriteLine("子系统方法一");}
}class SubSystemTwo
{public void MethodTwo(){Console.WriteLine("子系统方法二");}
}class SubSystemThree
{public void MethodThree(){Console.WriteLine("子系统方法三");}
}class SubSystemFour
{public void MethodFour(){Console.WriteLine("子系统方法四");}
}//外观类,他需要了解所有的子系统的方法或属性,进行组合,以备外界调用
class Facade
{SubSystemOne one;SubSystemTwo two;SubSystemThree three;SubSystemFour four;public Facade(){one = new SubSystemOne();two = new SubSystemTwo();three = new SubSystemThree();four = new SubSystemFour();}public void MethodA(){Console.WriteLine("\n方法组A() -----");one.MethodOne();two.MethodTwo();three.MethodThree();four.MethodFour();}public void MethodB(){Console.WriteLine("\n方法组B()----");two.MethodTwo();three.MethodThree();}
} 

涉及到的知识

①、构造方法

又叫构造函数。

目的:对类进行初始化。

特点:与类同名,没有返回值,不需要void,在new时候调用。

所有类都有构造方法,如果你不编码则系统默认生成空的构造方法,若你有定义的构造方法,那么默认的构造方法就会失效了

形式:比方说有一个猫出生下来就叫点点,Cat cat = new Cat("点点");

②、修饰符

public:共有的,所有的类都可以访问,

internal:同一项目的可以访问,类默认是这个

private:私有的,只允许同一类中的成员访问,子类都不可访问,成员默认是这个

protected:保护的,只有子类可以访问

③、字段、属性

字段:程序开发中常见的常量或变量,它是类的一个构成部分,它使得类和结构可以封装数据。默认private,只允许本类可以访问,客户端不可以访问

属性:是一个方法或一对方法。默认public,有get和set两个方法

get访问器返回与声明的属性相同的数据类型,表示的意思是调用时可以得到内部字段的值或引用;

set访问器没有显式设置参数,但它有一个隐式参数,用关键字value表示,它的作用是调用属性时可以给内部的字段或赋值。

为什么要使用get和set?

由于属性中可以包含大量的语句,因此可以对赋予的值进行检查,如果值不安全或者不符合要求,就可以进行提示,这样就可以避免因为给属性设置了错误的值而导致的错误

private int age;
public int Aget
{get{return age;}set{if(value<0 && value>100){Console.WriteLine("输入的不合理!");}else{age =value;}
}

④、封装

每个对象都包含它能进行操作所需要的所有信息,这个特性称为封装,因此对象不必依赖其他对象来完成自己的操作。

有什么好处?

  • 良好的封装能够减少耦合;
  • 类内部的实现可以自由地修改;
  • 类具有清晰的对外接口。

⑤、六大关系

关联(Association):对于两个相对独立的对象,当一个对象的实例与另一个对象的一些特定实例存在固定的对应关系时,这两个对象之间为关联关系。

实现:成员变量

图形:实线+箭头

class Student
{public School school;public School(){}
}clss School
{public School(){}
}

聚合(Aggregation):整体和个体,个体可以脱离整体而独立存在。

实现:成员变量、构造方法的参数

图形:实线+空心菱形

 

⑥、六大原则

迪米特法则

如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。

依赖倒转原则

-高层模块不应该依赖底层模块。两个都应该依赖抽象(接口/抽象类)。

-抽象不应该依赖细节(具体类)。细节应该依赖抽象。

无论主板、CPU、内存、硬盘都是在针对接口设计的。CPU作为主板上一个可移动的、可扩展的部分,在设计主板的时候只需要把接口定义好,内部再复杂我也不让外界知道,而主板只需要预留与CPU阵脚的插槽就可以了。内存、硬盘、显卡都是如此,哪部分坏了直接更换那部分就行了,而不会导致整个主板全部都要换。

 

依赖倒转其实可以说是面向对象设计的标准

开闭原则

多扩展开放,对修改关闭。

 

相关文章:

设计模式—外观模式(Facade)

目录 一、什么是外观模式&#xff1f; 二、外观模式具有什么优点吗&#xff1f; 三、外观模式具有什么缺点呢&#xff1f; 四、什么时候使用外观模式&#xff1f; 五、代码展示 ①、股民炒股代码 ②、投资基金代码 ③外观模式 思维导图 一、什么是外观模式&#xff1f;…...

Stack Overflow开发者调查发布:AI将如何协助DevOps

Stack Overflow 发布了开创性的2023年度开发人员调查报告 [1]。报告对 90,000 多名开发人员进行了调查&#xff0c;全面展示了当前软件开发人员的体验。接下来&#xff0c;本文将重点介绍几项重要发现&#xff0c;即重要编程语言和工具偏好、人工智能在开发工作流程中的应用以及…...

去掉鼠标系列之二:Sublime Text快捷键使用指南

系列之二&#xff0c;Sublime Text。 Sublime Text 是我们常用的文本工具&#xff0c;常常要沉浸如其中使用&#xff0c;而不希望被鼠标打扰&#xff0c;所以也记录一下。 学会下面这些快捷键&#xff0c;基本上就不需要移动鼠标啦。 1&#xff0c;CtrlK&#xff0c;CtrlV …...

docker-compose安装node-exporter, prometheus, grafana

基础 exporter提供监控数据 prometheus拉取监控数据 grafana可视化监控数据 准备 全部操作在/root/mypromethus中执行 node_exporter docker-compose -f node-exporter.yaml up -d # web访问&#xff0c;查看node_exporter采集到的数据 http://192.168.1.102:9101/metrics…...

企业架构LNMP学习笔记10

1、Nginx版本&#xff0c;在实际的业务场景中&#xff0c;需要使用软件新版本的功能、特性。就需要对原有软件进行升级或重装系统。 Nginx的版本需要升级迭代。那么如何进行升级呢&#xff1f;线上服务器如何升级&#xff0c;我们选择稳定版本。 从nginx的1.14版本升级到ngin…...

[国产MCU]-W801开发实例-I2C控制器

I2C控制器 文章目录 I2C控制器1、I2C控制器介绍2、I2C驱动API2、I2C简单使用示例1、I2C控制器介绍 I2C总线是一种简单、双向二线同步串口总线。I2C总线设备之间通信只需两根线即可完成设备之间的数据传输。 I2C总线设备分为主机和从机,这取决于数据传输方向。I2C总线上的主机…...

植物根系基因组与数据分析

1.背景 这段内容主要是关于植物对干旱胁迫的反应&#xff0c;并介绍了生活在植物体内外以及根际的真菌和细菌的作用。然而&#xff0c;目前对这些真菌和细菌的稳定性了解甚少。作者通过调查微生物群落组成和微生物相关性的方法&#xff0c;对农业系统中真菌和细菌对干旱的抗性…...

2.3 数据模型

思维导图&#xff1a; 前言&#xff1a; 我的理解&#xff1a; 这段话介绍了概念模型和数据模型之间的关系&#xff0c;以及数据模型的定义和重要性。具体解读如下&#xff1a; 1. **概念模型**&#xff1a;它是一种描述现实世界数据关系的抽象模型&#xff0c;不依赖于任何…...

RT-Thread 中断管理学习(一)

中断管理 什么是中断&#xff1f;简单的解释就是系统正在处理某一个正常事件&#xff0c;忽然被另一个需要马上处理的紧急事件打断&#xff0c;系统转而处理这个紧急事件&#xff0c;待处理完毕&#xff0c;再恢复运行刚才被打断的事件。生活中&#xff0c;我们经常会遇到这样…...

学习周报9.3

文章目录 前言文献阅读一摘要挑战基于时间序列的 GAN 分类 文献阅读二摘要介绍提出的模型:时间序列GAN (TimeGAN) 代码学习总结 前言 本周阅读两篇文献&#xff0c;文献一是一篇时序生成方面的综述&#xff0c;主要了解基于时间序列 的GAN主要分类以及时间序列GAN方面面临的一…...

win10 查看指定进程名的端口号

在 Windows 10 的任务管理器中也可以查看端口号。请按下面的步骤操作&#xff1a; 打开任务管理器&#xff0c;可以通过按下快捷键 CtrlShiftEsc 或者右键点击任务栏后选择任务管理器来打开。点击“性能”选项卡&#xff0c;然后点击左侧的“打开资源监视器”。在资源监视器中…...

函数的递归调用

1、什么是函数的递归调用&#xff1f; 其实说白了就是在函数的内部再调用函数自己本身 function fun(){fun() } 2、用递归解决问题的条件 &#xff08;1&#xff09;一个问题是可以分解成子问题&#xff0c;子问题的解决办法与最原始的问题解决方法相同 &#xff08;2&…...

李宏毅机器学习笔记:RNN循环神经网络

RNN 一、RNN1、场景引入2、如何将一个单词表示成一个向量3种典型的RNN网络结构 二、LSTMLSTM和普通NN、RNN区别 三、 RNN的训练RNN与auto encoder和decoder 四、RNN和结构学习的区别 一、RNN 1、场景引入 例如情景补充的情况&#xff0c;根据词汇预测该词汇所属的类别。这个时…...

基于JavaWeb和mysql实现校园订餐前后台管理系统(源码+数据库)

一、项目简介 本项目是一套基于JavaWeb和mysql实现网上书城前后端管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、项目文档、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都…...

CNN 01(CNN简介)

一、卷积神经网络的发展 convolutional neural network 在计算机视觉领域&#xff0c;通常要做的就是指用机器程序替代人眼对目标图像进行识别等。那么神经网络也好还是卷积神经网络其实都是上个世纪就有的算法&#xff0c;只是近些年来电脑的计算能力已非当年的那种计算水平…...

AI大模型的使用-让AI帮你写单元测试

1.体验多步提示语 我们本节就让AI帮我们写一个单元测试&#xff0c;全程用AI给我们答案&#xff0c;首先单元测试前需要有代码&#xff0c;那么我们让AI给我们生成一个代码&#xff0c;要求如下&#xff1a; 用Python写一个函数&#xff0c;进行时间格式化输出&#xff0c;比…...

vscode调教配置:快捷修复和格式化代码

配置vscode快捷键&#xff0c;让你像使用idea一样使用vscode&#xff0c;我们最常用的两个功能就是格式化代码和快捷修复&#xff0c;所以这里修改一下快捷修复和格式化代码的快捷键。 在设置中&#xff0c;找到快捷键配置&#xff1a; 然后搜索&#xff1a;快捷修复 在快捷键…...

pear admin 后端启动

pear admin 后端启动 一、项目结构二、启动 一、项目结构 应用结构&#xff1a; Pear Admin Flask ├─applications # 应用 │ ├─rights # │ ├─system # 静态资源文件 │ ├─users # │ └─views # 视图部分 ├─common # 公共模块 ├─models # 数据模…...

C++:输出系统时间(及报错处理)

#include <iostream> #include <ctime>using namespace std;int main() {// 基于当前系统的当前日期/时间time_t now time(0);cout << "1970 到目前经过秒数:" << now << endl;tm* ltm localtime(&now);// 输出 tm 结构的各个组…...

使用Windbg动态调试排查软件启动不了的问题

目录 1、问题说明 2、初步分析 3、使用Windbg启动程序进行动态调试 4、进一步分析 5、何时使用Windbg静态分析&#xff1f;何时使用Windbg进行动态调试&#xff1f; 6、最后 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...