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

news2024/10/6 0:31:43

目录

一、什么是外观模式?

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

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

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

五、代码展示

①、股民炒股代码

②、投资基金代码

③外观模式


思维导图

 

一、什么是外观模式?

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

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();         //实例化股票1
            gu2 = new Stock2();         //实例化股票2
            gu3 = new Stock3();         //实例化股票3
            nd1 = new NationalDebt1();  //实例化国债1
            rt1 = 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阵脚的插槽就可以了。内存、硬盘、显卡都是如此,哪部分坏了直接更换那部分就行了,而不会导致整个主板全部都要换。

 

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

开闭原则

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

 

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

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

相关文章

《Flink学习笔记》——第四章 Flink运行时架构

4.1 系统架构 Flink运行时架构 Flink 运行时由两种类型的进程组成&#xff1a;一个 JobManager 和一个或者多个 TaskManager。 1、作业管理器&#xff08;JobManager&#xff09; JobManager是一个Flink集群中任务管理和调度的核心&#xff0c;是控制应用执行的主进程。也就…

Java之API详解之Object类的详细解析

4 Object类 4.1 概述 tips&#xff1a;重点讲解内容 查看API文档&#xff0c;我们可以看到API文档中关于Object类的定义如下&#xff1a; Object类所在包是java.lang包。Object 是类层次结构的根&#xff0c;每个类都可以将 Object 作为超类。所有类都直接或者间接的继承自该类…

JavaScript设计模式(二)——简单工厂模式、抽象工厂模式

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

网络防御和入侵检测

网络防御和入侵检测是维护网络安全的关键任务&#xff0c;可以帮助识别和阻止未经授权的访问和恶意行为。以下是一些基本的步骤和方法&#xff0c;用于进行网络防御和入侵检测。 网络防御&#xff1a; 防火墙设置&#xff1a; 部署防火墙来监控和控制网络流量&#xff0c;阻止…

禅道后台命令执行漏洞 (二)

漏洞简介 禅道是第一款国产的开源项目管理软件。它集产品管理、项目管理、质量管理、文档管理、 组织管理和事务管理于一体&#xff0c;是一款专业的研发项目管理软件&#xff0c;完整地覆盖了项目管理的核心流程。禅道管理思想注重实效&#xff0c;功能完备丰富&#xff0c;操…

多线程基础篇

我们平常说的一个程序&#xff0c;一个程序中有声音&#xff0c;图片&#xff0c;字幕 实际上是一个进程中有多个线程 main线程是主线程。 多核&#xff0c;多个cpu&#xff0c;多个线程&#xff0c;切换的很快 单核的话是一个cpu,某一时间只能是一个线程&#xff0c;但是因为…

NLNet、GCNet、RTNet三种多头注意力网络的对比与分析

目录 一、中心思想 二、网络结构的异同点 三、网络结构的改进 3.1 GCNet的改进 3.2 RTNet的改进 四、总结 一、中心思想 三种网络最终目的都是为了捕获远程依赖关系或是全局上下文信息以增强目标检测或是目标分割的效果。 NLNet&#xff1a;卷积运算只能一次处理一个局…

C#,《小白学程序》第七课:列表(List)应用之一“编制高铁车次信息表”

1 文本格式 /// <summary> /// 车站信息类 class /// </summary> public class Station { /// <summary> /// 编号 /// </summary> public int Id { get; set; } 0; /// <summary> /// 车站名 /// </summary>…

17.CSS发光按钮悬停特效

效果 源码 <!DOCTYPE html> <html> <head><title>CSS Modern Button</title><link rel="stylesheet" type="text/css" href="style.css"> </head> <body><a href="#" style=&quo…

【Go 基础篇】探索Go语言中Map的神奇操作

嗨&#xff0c;Go语言的学习者们&#xff01;在编程世界中&#xff0c;Map是一个强大而又有趣的工具&#xff0c;它可以帮助我们高效地存储和操作键值对数据。Map就像是一本字典&#xff0c;可以让我们根据关键字&#xff08;键&#xff09;快速找到对应的信息&#xff08;值&a…

Windows版本Docker安装详细步骤

文章目录 下载地址安装异常处理docker desktop requires a newer wsl 下载地址 https://desktop.docker.com/win/stable/Docker%20Desktop%20Installer.exe 安装 双击下载的文件Docker Desktop Installer.exe进行安装 点击OK 开始安装 安装完成点击Close and restart&…

JavaScript—面向对象、作用域

C#&#xff1a;从类继承 js&#xff1a;从对象继承 什么叫继承&#xff1f; 模板&#xff08;类&#xff09; 原型继承&#xff08;实体&#xff09; 有一个对象存在&#xff0c;构造函数设置原型为这个对象 创建出来的对象就继承与这个对象&#xff08;从对象那里继承&am…

ElasticSearch基础知识汇总

文章目录 前言一、认识ElasticSearch1.正向索引和倒排索引2. MySql与ElasticSearc3.IK分词器 二、ES索引库操作1.mapping映射属性2.索引库的CRUD 三、ES文档库操作 前言 Elasticsearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基…

Kali Linux进行移动应用安全测试

使用Kali Linux进行移动应用安全测试是一项关键任务&#xff0c;可以帮助识别和修复移动应用中的安全漏洞。以下是一个基本的步骤指南&#xff0c;展示如何在Kali Linux中进行移动应用安全测试。 步骤&#xff1a; 准备环境&#xff1a; 确保 已经安装了Kali Linux&#xff0c…

开箱报告,Simulink Toolbox库模块使用指南(五)——S-Fuction模块(C MEX S-Function)

文章目录 前言 C MEX S-Function 算法原理 原始信号创建 编写S函数 仿真验证 Tips 分析和应用 总结 前言 见《开箱报告&#xff0c;Simulink Toolbox库模块使用指南&#xff08;一&#xff09;——powergui模块》 见《开箱报告&#xff0c;Simulink Toolbox库模块使用…

fastjson利用templatesImpl链

fastjson1.2.24 环境&#xff1a; pom.xml&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLoc…

在 Python 中逐步构建 DCF(贴现流)估值

Building A DCF Valuation in Python, Step by Step | by Roi Polanitzer | Medium 说明 这是一个真实的&#xff0c;以色列国土内的公司业务评估案例。在本文中&#xff0c;我将演示如何使用python中的DCF方法对以色列系统和应用程序公司进行业务评估。因为存在许多业务术语&a…

JVM 访问对象的两种方式

Java 程序会通过栈上的 reference 数据来操作堆上的具体对象。由于 reference 类型在《Java 虚拟机规范》里面只规定了它是一个指向对象的引用&#xff0c;并没有定义这个引用应该通过什么方式去定位、访问到堆中对象的具体位置&#xff0c;所以对象访问方式也是由虚拟机实现而…

音视频技术开发周刊 | 308

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 OpenAI首席科学家最新访谈&#xff1a;对模型创业两点建议、安全与对齐、Transformer够好吗&#xff1f; OpenAI首席科学家Ilya Sutskever最近和他的朋友Sven Strohband进…

算法设计 || 第6题:基于最小成本检索的分支界限算法求解15谜问题

用基于最小成本检索的分支界限算法求解15谜问题 要求利用成本估计函数C^(X)&#xff0c; C^(X)为节点x排列中不在其目标位置上的牌的总张数&#xff08;不包括空格牌&#xff09;。 现定义空格牌的上下左右四种活动&#xff0c; 按四种活动分别生成其状态空间树&#xff0c;…