软件体系结构
软件体系结构
质量属性:
开发期质量:可扩展性,可复用性,可维护性等;
运行期质量:正确性,健壮性,性能,可靠性,容错性,易用性,安全性,可移植性,兼容性。
设计原则:
-
面向接口编程(Program to interfaces, not to implementations)
-
多用组合,少用继承(Favor composition over inheritance)
-
Principle of Least Knowledge(Law of Demeter)
-
单一职责原则(Single Responsibility Principle):就一个类而言,应该仅有一个引起它变化的原因。
-
开闭原则(Open-Closed Principle):软件实体对扩展是开放的,但对修改是关闭的,即在不修改一个软件实体的基础上去扩展其功能。抽象化是开闭原则的关键
-
里氏代换原则(Liskov Substitution Principle):在软件系统中,一个可以接受基类对象的地方必然可以接受一个子类对象。里氏代换原则是实现开闭原则的重要方法之一。
-
依赖倒置原则(Dependency Inversion Principle):要针对抽象层编程,而不要针对具体类编程。实现开闭原则的关键是抽象化,并且从抽象导出具体化实现,如果说开闭原则是面向对象设计的目标的话,那么依赖倒置原则就是面向对象设计的主要手段。依赖注入:构造注入,设置注入,接口注入
-
接口隔离原则(Interface Segregation Principle):使用多个专门的接口来取代一个统一的接口。
-
分离关注点(Principle of Separation of Concerns):"Organize software into separate components(pieces) that are as independent as possible."
软件风格:
Model-View-Controller(pattern)
MVC模式(Model-view-controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)
MCV模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。
控制器(Controller):负责转发请求,对请求进行处理。
试图(View):界面设计人员进行图形界面设计。
模型(Model):程序员编写程序应有的功能(实现算法等等)、数据专家进行数据管理和数据库设计(可以实现具体的功能)
将应用程序划分为三种组件,模型-试图-控制器(MVC)设计定义它们之间的相互作用。
模型(Model):用于封装与应用程序的业务逻辑相关的数据以及数据的处理方法。"Model"有对数据直接访问的权利,例如对数据库的访问。"Model"不依赖"View"和"Controller",也就是说,Model不关心它会被如何显示或是如何被操作。但是Model中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些勇于监视此Model的View必须事前在此Model上注册,从而,View可以了解在数据Model上发生的改变。
视图(View)能够实现数据有目的的显示(理论上,这不是必需的)。在View中一般没有程序上的逻辑。为了实现View上的刷新功能,View需要访问它监视的数据模型(Model),因此应该事前在被它监视的数据那里注册。
控制器(Controller)起到了额不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。"事件"包括用户的行为和数据Model上的改变。
实例Java平台上实现的MVC模型
视图(View)
在J2EE应用程序中,视图(View)可能由Java Server Page(JSP)担任。生成View的代码则可能是一个servlet的一部分,特别是在客户端服务端交换的时候。
控制器(Controller)
J2EE应用中,Controller可能是一个servlet。除了可直接以J2EE来撰写外,亦可用其他框架来撰写,常见的有Struts2,Spring Framework…等等。
模型(Model)
Model则是由一个实体Bean来实现。
C/S(Client-Server)
C/S软件是基于资源不对等,且为实现共享而提出来的。C/S体系结构主要有三个主要组成部分:数据库、服务器、客户应用程序和网络。优点:具有强大的数据操作和事务处理能力;对于软件和硬件的变化显示出强大的适应性和灵活性;将大的应用处理任务分到许多通过网络连接的低成本计算机上。缺点:开发成本高;客户端程序设计复杂;软件维护和升级困难。
管道过滤器风格(Pipe-and-Filter)
每一个组件都有一组输入和输出,组件读输入的数据流,经过内部处理,然后产生输出的数据流。过滤器风格的连接件就像是数据流传输的管道,将一个过滤器的输出传到另一个过滤器的输入。
分层系统(Layered/Tiered Architecture)
组织成一个层次结构,每一层都为上一层提供了相应的服务,并且接受下一层的服务。在分层系统的一些层次中构件实现了虚拟机的功能。实例:分层的操作系统
端到端(Peer-to-Peer)
黑板系统/仓库系统(Blackboard/Repository)
组件:中心数据结构(仓库)和一些独立构件的集合。
仓库和在系统中很重要的外部组件之间的相互作用
实例:需要使用一些复杂表征的信号处理系统
基于事件的隐式调用(Event-Based Architecture(PubSub))
组件不直接调用一个过程,而是触发或广播一个或多个事件。系统中的其他组件中的过程在一个或多个事件中祖册,当一个事件被触发,系统自动调动这个事件中注册的所有过程。这种风格的组件是一个模块,这些模块可以是一些过程,又可以是一些事件的集合。不变量:事件的触发者并不知道哪些组件会被这些事件影响(观察者模式-Observer)
实例:数据库管理系统,用户界面。
SOA(Service-Oriented Architecture)
面向服务的体系结构是一个组件模型,它将应用的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。阿里的dubbox是国内现在应用最多的用来实现SOA的框架。它将服务注册到企业服务总线上,当某个系统需要调用其他系统中数据的时候直接从企业服务总线上获取,而不是端到端的获取,从而减少了系统的复杂度。
RESTF(representational state transfer)表述性状态转移
Rest是web服务的一种架构风格;使用HTTP,URI,XML,JSON,HTML等广泛流行的标准和协议;轻量级,跨平台,跨语言的架构设计。它是一种设计风格,不是一种标准,是一种思想。
Rest架构的主要原则:
-
网络上的所有事情都被抽象为资源
-
每个资源都有一个唯一的资源标识符
-
同一个资源具有多种表现形式(xml,json等)
-
对资源的各种操作不会改变资源标识符
-
所有的操作都是无状态的
-
符合REST原则的框架方式即可成为RESTful
什么是Restful:
对应的中文是rest式的;Restful web service是一种常见的rest的应用,是遵守了rest风格的web服务;rest式的web服务是一种ROA(The Resource-Oriented Architecture)(面向资源的架构)
为什么会出现Restful
在Restful之前的操作:
http://127.0.0.1/user/query/1 GET 根据用户id查询用户数据
http://127.0.0.1/user/save POST 新增用户
http://127.0.0.1/user/update POST 修改用户信息
http://127.0.0.1/user/delete GET/POST 删除用户信息
RESTful用法:
http://127.0.0.1/user/1 GET 根据用户id查询用户数据
http://127.0.0.1/user POST 新增用户
http://127.0.0.1/user PUT 修改用户信息
http://127.0.0.1/user DELETE 删除用户信息
之前的操作是没有问题的,大神认为是有问题的,有什么问题呢?你每次请求的接口或者地址,都在做描述,例如查询的时候用了query,新增的时候用了save,其实完全没有这个必要,我使用了get请求,就是查询,使用post请求,就是新增的请求,我的意图很明显,完全没有必要做描述,这就是为什么有了restful
如何使用
总结:restful就是旧技术,新风格。
大泥球风格(big ball of mud):大泥球风格就是没有任何清楚的结构,杂乱无章、错综复杂,邋遢不堪、随意拼贴的大堆代码。
控制反转与依赖注入
什么是控制?如下图所示,我们看到了软件系统中对象的高耦合现象。全体齿轮的转动由一个对象来控制,如类B
什么是控制反转?是用来对对象进行解耦。借助第三方实现具有依赖关系的对象之间的解耦。这个第三方就是ioc容器。引入了ioc容器后,对象A、B、C、D之间没有了依赖关系,全体齿轮转动的控制权交给容器。这时候齿轮转动控制权不属于任何对象,而属于ioc容器,所以控制权反转了,从某个对象转到了ioc容器。
什么是依赖注入?
什么是依赖?依赖是指一种关系,如果在类A中创建了类B的实例,我们说类A依赖类B。下面有一个例子:
出现的问题(problems):
问题1:如果现在要改变类B生成方式,如需要new B(string name)初始化 B,需要修改类A中的源代码;
问题2:如果想测试不同B对象对A的影响很困难,因为B的初始化被写死在了A的构造函数中;
问题3:如果要对类B的实例进行调试时,就必须在类A中对类B的实例进行测试,增加了测试的难度和复杂度;因为当出现问题时,不知道是类A的问题还是类B的问题。
解决方法:
依赖注入定义:将B对象实例作为类A的构造器参数进行传入,在调用类A构造器之前,类B实例已经别初始化好了。像这种非自己主动初始化依赖,而通过外部传入依赖对象的方式,我们就称为依赖注入。
依赖反转
根据依赖注入的定义:被依赖者对象并不是依赖自己主动初始化,而是通过外部传入被依赖者的方式,那么背依赖者对象类型可以是其本身,也可以使其实现类或继承子类;
所以,经过分析,被依赖者的对象类型,并不是依赖者自身可以决定的,(当然传统的程序设计方式是依赖者决定的),而是由外部创建者决定的,所以被依赖者类型的决定权反转了。对于spring来说,就是由spring容器决定的;
依赖反转定义:被依赖者的对象类型并不是由依赖者自身可以决定的,而是由外部创建者决定的,外部传入什么类型的对象就是什么类型的对象,依赖者对其一无所知;
框架与库
有一个基本的特征是框架一般指的是会调用你的代码,控制权从你写的程序手中转移到框架中,而库一般是用来被你调用。
库和框架都是一种有别于软件、面向程序开发者的产品形式。正因为如此,也有很多人误认为库就是框架,或者认为指定语言的库就是框架。
库的英文单词为Library(简称为Lib),框架的英文为Framework。
库是将代码集合成一个产品,供程序员调用。面向对象的代码组织形式而成的库也叫类库。面向过程的代码组织形式而成的库也叫函数库。在函数库中的可以直接使用的函数叫库函数。开发者在使用库的使用,只需要使用库的一部分类或函数,然后继续实现自己的功能。
框架则是为解决一个(一类)问题而开发的产品,框架用户一般只需要使用框架提供的类或函数,即可实现全部功能。可以说,框架是库的升级版。
开发者在使用框架的时候,必须使用这个框架的全部代码。
框架和库的比较可以想象为:
假如我们要买一台电脑。框架为我们提供了已经装好的电脑,我们只要买回来就能用,但你必须把整个电脑买回来。这样用户自然轻松许多,但会导致很多人用一样的电脑,或你想自定义某个部件将需要修改这个框架。而库就如自己组装的电脑。库为我们提供了很多部件,我们需要自己组装,如果某个部件未提供,我们也可以自己做。库的使用非常灵活,但没有框架方便。
体系结构中的模型
To help reason and communicate about the design of complex software as a whole.
(为了帮助理解与沟通复杂软件作为一个整体的设计)
Canonical Model Structure(规范化模型结构)
Domain Model(领域模型): The facts about the world(真实世界的事实)
Design Model(设计模型): The design decisions made about the software.(软件开发中的设计决策)
Code Model(代码模型): The source code implementation of a system.(实现系统的源代码)
领域模型:领域模型表达了与系统相关的现实世界的不变事实。就Yinzer系统而言,这些相关事实包括如广告(Ads)和联系方式(Contacts)等重要类型的定义、类型之间的关系,以及描述类型与关系如何因时而变的行为。通常,无法控制领域模型,例如,无法决定一周只能拥有6天,或者要求每周举行生日宴会。
设计模型:相反,设计模型主要是在设计者控制下。需要构建的系统不仅会显示在领域模型中,还会在设计模型中出现。设计模型是设计承若的一部分。这就是说,可以推迟实现那些未曾决策而又事关设计的某些细节(通常出于更低层次),直到获得代码模型。设计模型由递归嵌套的边界模型和内部模型组成。边界模型与内部模型描述了相同的内容(就像组件或模块),但边界模型只涉及公共的可见接口,而内部模型还介绍了内部设计。
代码模型:代码模型既是系统的源代码实现,又相当于一个模型。它可以是实际的Java代码,或通过运行工具将代码转换为UML的结果。关键还在于它包含了完整的对设计的承若。
设计模型往往会忽略对低风险部分的描述,只要开发者理解了整个设计和架构,设计就是充分的。然而,设计模型对设计的承若是不完整的,代码模型则不然,至少它对设计的承若完整到足以在机器上运行。
4+1视图模型
逻辑视图:分析,设计(结构)
实现视图:编程(软件开发)
过程视图:系统集成(性能,吞吐量,可扩展性)
部署视图:系统工程(系统拓扑,分发与安装,通信)
用例视图:用来描述功能
软件体系结构
软件体系结构包组件(Component)、连接件(Connector)和约束(Constraint)三大要素。
组件:可以是一组代码,如程序的模块;也可以是一个独立的程序,如数据库服务器。连接件可以是过程调用,管道,远程调用等,用于表示组件之间的相互作用。一个软件体系结构还包括某些约束,约束一般对象连接时的规则或指明连接的势态和条件。软件体系结构是设计过程的一个层次,它处理那些超越算法和数据结构的设计,研究整体设计和描述方法。
模块(module)
模块(module)是实现制品的集合,例如,源代码(类、函数、过程、规则等)、配置文件、数据库模式定义。
模块可以把相关的代码进行分组,只暴露接口而隐藏实现。在这一点上,模块和类相似,由于模块常常包含很多类和其他的制品,其规模比类要大。模块的接口和内部的那些接口是不同的。模块可以依赖(depend)于另一个模块。一个模块可以被包含在另一个模块内,这个关系称为嵌套(nesting),也可以称为包含。
端口(Ports)
所有进出组件的通信都是通过组件上的端口(ports)来完成的。一个组件支持的所有公开可用的方法,以及要响应的所有公开事件,都会在组件端口中进行规定。如果一个组件要给另一个组件发送消息,要写数据库,要获取互联网上的信息,就必须通过端口。端口通过操作来透露行为。客户端常常必须以一种特定的次序或者协议来调用操作。端口可以是有状态的,这尤其便于跟踪协议的状态。
适应变化(Adapting to Change)
-
应该可以很容易地定位到哪一个地方需要变化。It should be easy to locate the place where a change is needed
-
如果要改变单一制品的话,应当只在一处地方进行修改。A change to a single artifact in a program should be made in just one place
-
改变单一制品的话,不应当在其他地方进行改变。A change to an artifact should require no (or minimal) changes to the rest of the program
-
错误应当只出现在被改变的地方。An error introduced by the change should only affect the thing being changed
设计模式
To help reason about complex software's code
Strategy(behavioral)
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use if.
策略模式(Strategy Pattern)
定义:
定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。策略模式是一种对象行为型模式。
Strategy Pattern:Define a family of algorithms,encapsulate each one,and make them interchangeable.Strategy lets the algorithm vary independently from clients that use it.
优缺点:
策略模式主要有点在于对"开闭原则"的完美支持,在不修改原有系统的基础上可以更换算法或者增加新的算法,它很好地管理算法族,提高了代码的复用性,是一种替换继承、避免多重条件转移语句的实现方式;其缺点在于客户端必须知道所有的策略类,并理解其区别,同时在一定程度上增加了系统中类的个数,可能会存在很多策略类。
适合的场景:
在一个系统里面有许多类,他们之间的区别仅在于它们的行为,使用策略模式可以动态地让一个对象在许多行为中选择一种行为;一个系统需要动态地在几种算法中选择一种;避免使用难以维护的多重条件选择语句;希望在具体策略类中封装算法和与相关的数据结构。
类图:
Decorator(structural)
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
装饰模式(Decorator Pattern)
定义:动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。其别名有可以成为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。根据翻译的不同,装饰模型也有人称之为"油漆工模式",它是一种对象结构型模式。
适用环境:在不影响其他对象的情况下,以动态、透明的方式给的单个对象添加职责。需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。
Composite(structural)
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
组合模式(Composite Pattern)
定义:组合多个对象形成树型结构以表示"整体-部分"的结构层次。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性。
Composite Pattern:Compose objects into tress structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.
优缺点:
组合模式的主要优点在于可以方便地对层次结构进行控制,客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关心自己处理的是单个对象还是整个组合结构,简化了客户端代码;其缺点在于使设计变得更加抽象,且增加新构件时可能会产生一些问题,而且很难对容器中的构件类型进行限制。
适用场景:
需要表示一个对象整体或部分层次;让客户能够忽略不同对象层次的变化,客户端可以针对抽象构件编程,无需关心对象层次结构的细节;对象的结构是动态的并且复杂程度不一样,但客户需要一致地处理它们。
类图:
Simple Factory(idiom)
Lets a separate class (or method) decide what object to instantiate.
简单工厂模式(Simple Factory Pattern)
定义:又称为静态工厂方法(Static Factory Method)模式,它属于创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有相同的父类。
优缺点:
优点:
简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责,但是其最大的缺点在于工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码将会非常复杂。
适用场景:
工厂类负责创建的对象比较少
客户端只知道传入工厂类的参数,对于如何创建对象不关心。
类图
Factory Method(creational)
Define an interface for creating an object, but let subclasses decide which class to instantiate. Lets a class defer instantiation to subclass.
工厂方法模式(Factory Method Pattern)
定义:工厂方法模式(Factory Method Pattern)又称为工厂模板,也叫虚拟构造器(Virtual Constructor)模式或多态工厂(Polymorphic Factory)模式,它属于创建类型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
Factory Method Pattern: Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclasses.
优缺点:
工厂方法模式主要优点是增加新的产品类时无需修改现有系统,并封装了产品对象的创建细节,系统具有良好的灵活性和可扩展性;其缺点在于增加新产品的同时需要增加新的工厂,导致系统类的个数成对增加,在一定程度上增加了系统的复杂度。
使用场景:一个类不知道它所需要的对象的类;一个类通过其子类来指定创建哪个对象;将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子创建产品子类,需要时再动态指定。
类图:
Abstract Factory(creational)
Provides an interface for creating families of related or dependent objects without specifying their concrete classes.
抽象工厂模式(Abstract Factory Pattern)
定义:提供一个创建一系列相关或相互依赖对象接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。
Abstract Factory Pattern:Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
优缺点:
抽象工厂模式的主要有点是隔离了具体类的生成,使得客户并不需要知道什么被创建,而且每次可以通过具体工厂类创建一个产品族中的多个对象,增加或者替换产品族比较方便,增加新的具体工厂和产品族很方便;主要缺点在于增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对"开闭原则"的支持呈现倾斜性。
适用场景:
一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节;系统中有多于一个的产品族,而每次只使用其中某一产品族;属于同一个产品族的产品将在一起使用;系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖与具体实现。
类图:
State(behavioral)
A monolithic object's behavor is a function of its state, and it must change its behavior at run-time depending on that state.
状态模式(state Pattern)
定义:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。
适用场景:对象的行为依赖于它的状态(属性)并且可以根据它的状态改变而改变它的相关行为。代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,使客户类与类库之间的耦合增强。在这些条件语句包含了对象的行为,而且这些条件对应于对象的各种状态。
例子:
Observer(behavioral)
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
观察者模式(Observer Pattern)
定义:
定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅模式(Publish/Subscribe),模式-视图模式(Modle/View),源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式
Observer Pattern:Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.
优缺点:
观察者模式的主要优点在于可以实现表示层和数据逻辑层的分离,并在观察目标和观察者之间建立一个抽象的耦合,支持广播通信;其主要缺点在于如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到回花费很多时间,而且如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之进行循环调用,可能导致系统崩溃。
使用场景:
一个抽象模型有两个方面,其中一个方面依赖于另一个方面;一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变;一个对象必须通知其他对象,而并不知道这些对象是谁;需要在系统中创建一个触发链。
类图:
Singleton(Creational; anti-pattern)
Ensures a class has only instance, and provides a global point of access to it.
单例模式(Singleton Pattern)
定义:
单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
Singleton Pattern:Ensure a class has only one instance and provide a global point of access to it.
优缺点:
单例模式的主要优点在于提供了对唯一实例的受控访问并可以节约系统资源;其主要的缺点在于因为缺少抽象层而难以扩展,且单例类职责过重。
适用场景:
系统只需要一个实例对象;客户调用类的单个实例只允许使用一个公共访问点。
类图:
Adapter(structural)
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
适配器模式(Adapter Pattern)
定义:
将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
Adapter Pattern:convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
优缺点:
适配器模式的主要优点是将目标类和适配者类解耦,增加了类的透明性和复用性,同时系统的灵活性和扩展性都非常方便,符合"开闭原则";类适配器模式的缺点是适配器在很多编程语言中不能同时适配多个适配者类,对象适配器模式的缺点是很难置换适配者类的方法。
适用场景:
系统需要使用现有的类,而这写类的接口不符合系统道德需要;想要建议一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类一起工作。
类图
类适配器
对象适配器
Façade(structural)
Provide a unified interface to a set of interfaces in a subsystem. Façade defines a higher-level interface that makes the subsystem easier to use.
外观模式(Façade Pattern)
外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。
Façade Pattern:Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use.
优缺点:
外观模式主要优点在于对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易,它实现了子系统与客户之间的松耦合关系,并降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程;其缺点在于不能很好地限制客户使用子系统类,而且在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了"开闭原则"。
适用场景:要为一个复杂子系统提供一个简单接口;客户程序与多个子系统之间存在很大的依赖性;在层次化结构中,需要定义系统中每一层的入口,使得层与层之间不直接产生联系。
类图:
Proxy(structural)
Provide a surrogate or placeholder for another object to control access to it.
代理模式(Proxy Pattern)
给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的英文叫做Proxy或Surrogate,它是一种对象结构型模式。
Proxy Pattern:Provide a surrogate or placeholder for another object to control access to it.
优缺点:
代理模式的优点在于能够协调调用者和被调用者,在一定程度上降低了系统的耦合度;其缺点在于由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,并且实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
适用场景:
远程代理为一个位于不同的地址空间的对象提供一个本地的代表对象,它使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建,这个小对象称为虚拟代理。虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。
保护代理可以控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
类图
大部分的设计模型都有如下的通用规则。(Most design patterns work by following the same general process):
-
(识别程序中变化的部分)Identify the part of the program that changes(algorithm, state, method, constructor, etc)
-
(将变化的部分封装成一个类)Encapsulate that functionality into a class
-
(通过其他的类进行实例化)Make instances of the new class components(instance variables) of other classes.