zoukankan      html  css  js  c++  java
  • 第1部分设计模式FAQ(培训)

    用Singleton模式的解释进行了更新。 设计模式常见问题解答 什么是设计模式? 你能解释一下工厂模式吗? 你能解释一下抽象工厂模式吗? 你能解释一下构建器模式吗? 你能解释一下原型图案吗? 你能解释一下原型模式中的浅拷贝和深拷贝吗? 你能解释一下单例模式吗? 你能解释一下命令模式吗? 一个项目的设计模式 介绍 这里有一个关于设计模式的问答和格式。在本节中,我们将讨论工厂、抽象工厂、构建器、原型、浅原型和深原型、单例模式和命令模式。 , 你可以阅读我的其他设计模式FAQ部分相同在下面的链接:- 第2部分设计模式FAQ—解释器模式、迭代器模式、中介器模式、记忆器模式和观察者模式 第三部分FAQ的设计模式——状态模式、策略模式、访问者模式、适配器模式和飞重模式 第4部分设计模式FAQ—桥式模式、复合模式、装饰模式、Facade模式、责任链(COR)、代理模式和模板模式 什么是设计模式? 设计模式是为在给定上下文中重复出现的问题编制的经过试验和测试的解决方案。所以基本上你有了问题背景和建议的解决方案。设计模式在软件开发的初始阶段就以某种或其他形式存在。假设你想实现一种排序算法首先想到的是冒泡排序。问题是排序,解决方法是冒泡排序。设计模式也是如此。 哪三种主要的设计模式? 模式有三种基本分类:创建模式、结构模式和行为模式。 创建型模式 •抽象工厂:-创建多个类家族的实例 •Builder: -将对象构造与表示分离 •工厂方法:——创建多个派生类的实例 •Prototype:-一个完全初始化的要复制或克隆的实例 •Singleton:一个类中只能存在一个实例 注意:-记住创造模式的最好方法是记住ABFPS(亚伯拉罕成为第一任总统)。 结构模式 •适配器:-匹配不同类的接口。 桥:-将对象的抽象与实现分离。 复合:一个由简单对象和复合对象组成的树形结构。 •Decorator:-动态地向对象添加责任。 外观:表示整个子系统的单个类。 -一个用于高效共享的细粒度实例。 代理:一个代表另一个对象的对象。 中介:-定义类之间简化的通信。 •纪念品:-捕获并恢复对象的内部状态。 在程序中包含语言元素的一种方法。 •迭代器:-按顺序访问集合中的元素。 •Resp链:-在对象链之间传递请求的方法。 •Command:-将命令请求封装为对象。 状态:-当一个对象的状态改变时改变它的行为。 •策略:-将算法封装在类中。 观察者:-一种通知一些类的变化的方式。 •模板方法:-将算法的具体步骤延迟到子类。 访问者:-定义一个新的操作到一个类没有改变。 你能解释一下工厂模式吗? 工厂模式是创建模式的一种类型。你可以从工厂这个名字本身看出它的意思是要建造和创造一些东西。在软件架构中,世界工厂模式意味着集中创建对象。下面是一个客户机的代码片段,它有不同类型的发票。这些发票根据客户指定的发票类型创建。以下代码有两个问题:- 首先,我们有很多'新的'关键字分散在客户端。在其他方面,客户端装载了大量的对象创建活动,这可能使客户端逻辑非常复杂。 第二个问题是客户需要了解所有类型的发票。因此,如果我们要添加一个名为“InvoiceWithFooter”的发票类类型,我们需要在客户端中引用这个新类并重新编译客户端。 图:-不同类型的发票 以这些问题为基础,我们现在来看看工厂模式如何帮助我们解决同样的问题。下图“工厂模式”显示了两个具体的类“ClsInvoiceWithHeader”和“ClsInvoiceWithOutHeader”。 第一个问题是,这些类与客户端直接接触,这导致很多“新”关键字分散在客户端代码。通过引入一个新类' ClsFactoryInvoice '来消除这个问题,这个类负责创建所有的对象。 第二个问题是客户端代码同时知道具体的类,例如“ClsInvoiceWithHeader”和“ClsInvoiceWithOutHeader”。这导致重新编译添加新发票类型时的客户端代码。例如,如果我们添加了‘ClsInvoiceWithFooter’,客户端代码需要相应地进行更改和重新编译。为了解决这个问题,我们引入了一个通用接口' IInvoice '。具体类' ClsInvoiceWithHeader '和' ClsInvoiceWithOutHeader '继承并实现' IInvoice '接口。 客户端仅引用' IInvoice '接口,这导致客户端和具体类之间的零连接(' ClsInvoiceWithHeader '和' ClsInvoiceWithOutHeader ')。所以现在如果我们添加新的具体的invoice类,我们不需要在客户端更改任何东西。 在一行中,对象的创建由' ClsFactoryInvoice '负责,客户端与具体类的断开由' IInvoice '接口负责。 图:-工厂模式 下面是如何在c#中实现工厂模式的代码片段。为了避免重新编译客户端,我们引入了invoice接口' IInvoice '。具体类“ClsInvoiceWithOutHeaders”和“ClsInvoiceWithHeader”都继承并实现了“IInvoice”接口。 图:-接口和具体类 我们还引入了一个额外的类' ClsFactoryInvoice ',带有一个函数' getInvoice() ',它将根据' intInvoiceType '的值生成两个发票的对象。简而言之,我们将对象创建的逻辑集中在“ClsFactoryInvoice”中。客户端调用' getInvoice '函数来生成发票类。需要注意的最重要的一点是,客户端仅引用“IInvoice”类型,而工厂类“ClsFactoryInvoice”也提供了相同类型的引用。这有助于客户端与具体类完全分离,因此现在当我们添加新类和发票类型时,我们不需要重新编译客户端。 图:-生成对象的工厂类 你能解释一下抽象工厂模式吗? 抽象工厂是对基本工厂模式的扩展。抽象工厂帮助我们将类似的工厂模式类统一到一个统一的接口中。因此,基本上所有公共工厂模式现在都继承了一个公共抽象工厂类,该类将它们统一在一个公共类中。与工厂模式相关的所有其他内容与上一个问题中讨论的内容相同。 工厂类帮助我们集中创建类和类型。抽象工厂可以使相关的工厂模式保持一致,从而使客户端界面更加简化。 图:-抽象工厂统一了相关的工厂模式 现在我们已经了解了基本的知识,让我们来尝试理解抽象工厂模式是如何实际实现的细节。如前所述,我们通过继承将工厂模式类(factory1和factory2)绑定到一个公共抽象工厂(AbstractFactory接口)。工厂类位于具体类的顶部,这些类同样派生自公共接口。例如,在图“抽象工厂的实现”中,具体类“product1”和“product2”都继承了一个接口,即“common”。想要使用具体类的客户端将只与抽象工厂和具体类继承的公共接口交互。 图:抽象工厂的实现 现在让我们看看如何在实际代码中实际实现抽象工厂。我们有这样的场景,我们有UI创建活动的文本框和按钮通过他们自己的集中工厂类' ClsFactoryButton '和' ClsFactoryText '。这两个类都继承了通用接口“InterfaceRender”。工厂的' ClsFactoryButton '和' ClsFactoryText '都继承了公共工厂' ClsAbstractFactory '。图“AbstractFactory的示例”显示了这些类是如何安排的以及它们的客户端代码。关于客户端代码,需要注意的重要一点是它不与具体类交互。为了创建对象,它使用抽象工厂(ClsAbstractFactory),为了调用具体类实现,它通过接口“InterfaceRender”调用方法。因此' ClsAbstractFactory '类为两个工厂' ClsFactoryButton '和' ClsFactoryText '提供了一个公共接口。 图:-以抽象工厂为例 我们将运行抽象工厂的示例代码。下面的代码片段“抽象工厂和工厂代码片段”展示了工厂模式类如何从抽象工厂继承。 图:-抽象工厂和工厂代码片段 图“具体类的公共接口”具体类如何继承公共接口“InterFaceRender”,该接口在所有具体类中强制执行方法“render”。 图:-具体类的公共接口 最后是客户端代码,它使用接口“InterfaceRender”和抽象工厂“ClsAbstractFactory”来调用和创建对象关于该代码的重要一点是,它与具体类完全隔离。因此,任何具体类中的更改(如添加和删除具体类)都不需要客户端级别的更改。 图:-客户端、界面和抽象工厂 你能解释一下构建器模式吗? 生成器属于创建模式类别的类型。Builder模式帮助我们将复杂对象的构造与其表示分离开来,以便相同的构造过程可以创建不同的表示。当对象的构造非常复杂时,构建器模式非常有用。主要目的是分离对象的构造和它们的表征。如果我们能够分离结构和表征,我们就可以从同一结构中得到许多表征。 图:-建设者的概念 为了理解我们所说的构造和表示是什么意思,让我们以下面的“沏茶”序列为例。 从图中可以看出,通过同样的沏茶步骤,我们可以得到三种茶的表现形式(即不加糖的茶、加糖/牛奶的茶和不加牛奶的茶)。 图:-准备茶 现在让我们以软件世界中的一个实时示例来看看builder是如何分离复杂的创建和表示的。考虑我们有一个应用程序,我们需要同样的报告显示为' PDF '或' EXCEL '格式。图“请求报告”显示了实现此目标的一系列步骤。根据报表类型,创建一个新报表,设置报表类型,设置报表的页眉和页脚,最后我们得到要显示的报表。 图:-请求报告 现在让我们从不同的角度来看待这个问题,如图“不同的观点”所示。在“请求报告”中定义的相同流现在以表示和常见结构进行分析。这两种类型的报告的构建过程是相同的,但是它们会导致不同的表示。 图:-不同的观点 我们将使用相同的报表问题,并尝试使用构建器模式来解决相同的问题。当您想要实现构建器模式时,有三个主要部分。 •建造者:建造者负责定义单个零件的建造过程。构建器有那些单独的流程来初始化和配置产品。 Director: - Director从构建者那里获取这些单独的流程,并定义构建产品的顺序。 •产品:-产品是由建造者和总监协调生产的最终对象。 首先让我们看一下构建器类的层次结构。我们有一个名为“ReportBuilder”的抽象类,将从它生成自定义生成器,如“ReportPDF”生成器和“ReportEXCEL”生成器。 图:-构建器类层次结构 图“实际代码中的构建器类”显示了类的方法。要生成报表,我们需要首先创建一个新报表,设置报表类型(EXCEL或PDF),设置报表标题,设置报表页脚,最后获得报表。我们已经定义了两个自定义构建器,一个用于“PDF”(ReportPDF),另一个用于“EXCEL”(ReportExcel)。这两个自定义构建器根据报表类型在那里定义自己的流程。 图:-实际代码中的生成器类 现在让我们了解一下director是如何工作的。类' clsDirector '接受构建器并按顺序调用单个方法流程。因此,director就像一个驱动程序,它获取所有单独的进程,并按顺序调用它们以生成最终产品,在本例中就是报告。图“Director in action”显示了方法“MakeReport”如何调用单个流程,以通过PDF或EXCEL生成报告产品。 图:-导演在行动 构建器中的第三个组件是产品,在本例中它就是报表类。 图:-报告类 现在让我们看一下builder项目的俯视图。图“客户、建设者、总监和产品”展示了他们是如何实现建设者模式的。客户端创建director类的对象,并传递适当的构建器来初始化产品。根据构建器的不同,产品会被初始化/创建并最终发送到客户端。 图:-客户,建造商,总监和产品 输出是这样的。我们可以看到根据构建器显示两种报表类型及其标题。 图:-建造器的最终输出 你能解释一下原型图案吗? 原型模式属于创建模式的一部分。它为我们提供了一种从对象的现有实例创建新对象的方法。在一句话中,我们克隆了现有对象及其数据。通过克隆对克隆对象的任何更改都不会影响原始对象值。如果你认为通过设置对象我们可以得到一个克隆,那么你就错了。通过将一个对象设置为另一个对象,我们设置了对象BYREF的引用。所以陈队的新对象也改变了原来的对象。时了解BYREF基本更清楚地考虑下面的图时的BYREF”。下面是以下的顺序代码: 在第一步,我们已经创建了第一个对象即其中obj1 class1。在第二步中,我们创建了第二个物体即methoda class1。在第三步我们将旧的值对象即其中obj1旧值。在第四步中我们设置了其中obj1 methoda。我们在第五步改变methoda值。现在我们显示的值,我们发现对象的新值。 图:时,BYREf 上面的例子中得出的结论是,当设置为其他对象时设置BYREF对象。所以新对象值变化也改变了旧对象值。 有许多情况下,我们希望新副本对象变化不应该影响到旧的对象。这个问题的答案是原型模式。 让看我们如何使用c#实现相同的。在下面图“原型在行动”我们客户类的ClsCustomer需要克隆。这可以在c#中使用“MemberWiseClone”方法。在JAVA中我们有“克隆”的方法来达到相同的。在相同的代码我们还展示了客户端代码。我们已经创建了两个对象的客户类“其中obj1”和“methoda”。任何更改的methoda不会影响“其中obj1”,因为它是一个完整的克隆复制。 图:原型 你能解释一下浅拷贝和深拷贝在原型模式? 有两种类型的克隆为原型模式。一个是浅克隆你刚刚读的第一个问题。只在浅拷贝对象克隆,任何对象包含的对象不是克隆。例如考虑图“深克隆在行动”我们有一个客户类和我们有一个地址类聚合内部客户类。“MemberWiseClone”只会克隆customer类“ClsCustomer”而不是“ClsAddress”类。所以我们增加了MemberWiseClone address类的函数也。现在,当我们调用getClone的函数调用父克隆函数和还孩子克隆功能,导致克隆完整的对象。当父对象克隆与包含对象称为深克隆,当只有父母是克隆其称为浅克隆。 图:-深克隆 你能解释单例模式吗? 隐藏,复制Code

    Punch :-  Create a single instance of object and provides access to this single instance via a central point.

    情况在项目中,我们希望只有一个实例对象的创建和共享之间的客户。例如假设有以下两个类,货币和国家。 这些类加载主数据将会被一次又一次的项目。我们想分享类的一个实例获得性能优势不触及数据库一次又一次。 隐藏,复制Code

    public class Currency
        {
            List<string> oCurrencies = new List<string>();
            public Currency()
            {
                oCurrencies.Add("INR");
                oCurrencies.Add("USD");
                oCurrencies.Add("NEP");
                oCurrencies.Add("GBP");
    
            }
            public IEnumerable<string> getCurrencies()
            {
                return (IEnumerable<string>)oCurrencies;
            }
        }
    </string></string></string></string>

    隐藏,复制Code

    public class Country
        {
            List<string> oCountries = new List<string>();
            public Country()
            {
                oCountries.Add("India");
                oCountries.Add("Nepal");
                oCountries.Add("USA");
                oCountries.Add("UK");
    
            }
            public IEnumerable<string> getCounties()
            {
                return (IEnumerable<string>) oCountries;
            }
        }
    </string></string></string></string>

    实现单例模式是一个4步骤的过程。 步骤1:创建一个密封类私有构造函数 私有构造函数是非常重要的,这样客户不能直接创建对象的类。如果你还记得,这一模式的主要目的是创建一个单一实例的对象可以共享在全球范围内,所以我们不想给客户直接控制创建实例。 隐藏,复制Code

    public sealed class GlobalSingleton
        {
    private GlobalSingleton() { }
    
    	………..
    	……….
    	}

    步骤2:创建聚合对象的类(在本例中它是货币和国家),我们希望单一实例。 隐藏,复制Code

    public sealed class GlobalSingleton
        {
            // object which needs to be shared globally
            public Currency Currencies = new Currency();
            public Country Countries = new Country();

    步骤3:创建一个静态只读对象t他类本身,让同样的通过静态属性,如下所示。 隐藏,复制Code

    public sealed class GlobalSingleton
        {
    	….
    	…
    // use static variable to create a single instance of the object
    static readonly GlobalSingleton INSTANCE = new GlobalSingleton();
    
    public static GlobalSingleton Instance
            {
                get
                {
                  
                    return INSTANCE;
                }
            }       
        }

    步骤4:现在你可以使用单例对象从客户机使用以下代码。 隐藏,复制Code

    GlobalSingleton oSingle = GlobalSingleton.Instance;
    Country o = osingl1.Country;

    下面是单例模式的完整代码,我们上面所讨论的。 隐藏,复制Code

    public sealed class GlobalSingleton
        {
            // object which needs to be shared globally
            public Currency Currencies = new Currency();
            public Country Countries = new Country();
    
            // use static variable to create a single instance of the object
            static readonly GlobalSingleton INSTANCE = new GlobalSingleton();
    
            /// This is a private constructor, meaning no outsides have access.
            private GlobalSingleton() 
            { }
            
    public static GlobalSingleton Instance
            {
                get
                {
                  
                    return INSTANCE;
                }
            }       
        }

    你能解释命令模式吗? 命令模式允许请求作为一个对象存在。好让我们理解这意味着什么。考虑图的菜单和命令我们有不同的行为根据菜单点击。所以这取决于菜单点击我们传递一个字符串,将行动行动中的文本字符串。根据字符串的操作我们将执行行动。坏的代码是它有很多‘如果’条件使编码更神秘。 图:菜单和命令 命令模式将上述行动对象。实际上这些对象执行时执行命令。 正如前面说的每一个命令是一个对象。我们首先为每个动作准备单独的类即退出,开放,文件和打印。Al l以上行为是封装在类像退出行动是包裹在“clsExecuteExit”,开放的行动是包裹在“clsExecuteOpen”,打印操作是包裹在“clsExecutePrint”等等。所有这些类都继承自一个公共接口“IExecute”。图:对象和命令 使用所有action类我们可以调用程序。调用程序的主要工作是地图的动作类的行动。 所以我们增加了一个集合中的所有行为即arraylist。我们暴露“getCommand”方法接受一个字符串和回馈抽象对象“IExecute”。现在客户端代码整洁干净。所有的“如果”条件现在搬到“clsInvoker”类。 图:客户机调用者和清洁 以防你的全新设计模式或你真的不想读这个complete 文章确实看到我们的免费设计pattern 培训和面试问题/答案视频。 下面是一个很好的设计模式youtube视频一步一步这解释了如何使用设计模式在c#项目。 设计模式的一个项目 学习设计模式的最好方法是通过做一个项目。本教程教你模式的模式但如果你想使用一个项目学习设计模式的方法,点击这个链接。 本文转载于:http://www.diyabc.com/frontweb/news2068.html

  • 相关阅读:
    软件架构自学笔记-- 转载“腾讯数据库专家雷海林分享智能运维架构”
    软件架构自学笔记-- 架构设计与安全控制
    软件架构自学笔记——什么样的架构才是好的架构
    软件架构自学笔记----分享“去哪儿 Hadoop 集群 Federation 数据拷贝优化”
    软件架构自学笔记---架构分析
    软件架构自学笔记——非功能特性
    软件架构自学笔记——常见的软件架构(https://jiajunhuang.com/articles/2018_09_16-common_software_archtecture_pattern.md.html)
    微服务化的基石——持续集成
    微软开源大规模数据处理项目 Data Accelerator
    vs2019 cdkey 秘钥
  • 原文地址:https://www.cnblogs.com/Dincat/p/13456974.html
Copyright © 2011-2022 走看看