源码地址:https://github.com/weilanhanf/PythonDesignPatterns

说明:

外观模式又叫做门面模式。在面向对象程序设计中,解耦是一种推崇的理念。但事实上由于某些系统中过于复杂,从而增加了客户端与子系统之间的耦合度。例如:在家观看多媒体影院时,更希望按下一个按钮就能实现影碟机,电视,音响的协同工作,而不是说每个机器都要操作一遍。这种情况下可以采用外观模式,即引入一个类对子系统进行包装,让客户端与其进行交互。

外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。

结构说明:

外观模式包含如下角色: Facade: 外观角色 SubSystem:子系统角色

实例:

假设有一组火警报警系统,由三个子元件构成:一个警报器,一个喷水器,一个自动拨打电话的装置。

#当火警发生时,先警报器响起警报,喷水器开始喷水,最后开始拨打火警电话
class AlarmSensor:
def run(self):
print "Alarm Ring..."
class WaterSprinker:
def run(self):
print "Spray Water..."
class EmergencyDialer:
def run(self):
print "Dial 119..." #业务代码
if __name__=="__main__":
alarm_sensor=AlarmSensor()
water_sprinker=WaterSprinker()
emergency_dialer=EmergencyDialer()
alarm_sensor.run()
water_sprinker.run()
emergency_dialer.run()

打印结果为:

Alarm Ring...
Spray Water...
Dial 119...

虽然也完成了业务需求,但是明显的是客户的负担较重,客户端与子系统的耦合度太大。如果在多个业务场景中需要启动三个部件,复制粘贴当仍然可以解决。但是减少重复代码是应该会被很轻易想到的方法。这样,需要将其进行封装,在设计模式中,被封装成的新对象,叫做外观。

class AlarmSensor:
def run(self):
print("Alarm Ring...")
class WaterSprinker:
def run(self):
print("Spray Water...")
class EmergencyDialer:
def run(self):
print("Dial 119...") class EmergencyFacade:
"""
外观类中封装了对子系统的操作
"""
def __init__(self):
self.alarm_sensor=AlarmSensor()
self.water_sprinker=WaterSprinker()
self.emergency_dialer=EmergencyDialer()
def runAll(self):
self.alarm_sensor.run()
self.water_sprinker.run()
self.emergency_dialer.run() if __name__=="__main__":
emergency_facade=EmergencyFacade()
emergency_facade.runAll()

打印结果:

Alarm Ring...
Spray Water...
Dial 119...

完成了业务需求。

模式分析

根据“单一职责原则”,在软件中将一个系统划分为若干个子系统有利于降低整个系统的复杂性,一个常见的设计目标是使子系统间的通信和相互依赖关系达到最小,而达到该目标的途径之一就是引入一个外观对象,它为子系统的访问提供了一个简单而单一的入口。 外观模式也是“迪米特法则”的体现,通过引入一个新的外观类可以降低原有系统的复杂度,同时降低客户类与子系统类的耦合度。

外观模式要求一个子系统的外部与其内部的通信通过一个统一的外观对象进行,外观类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与外观对象打交道,而不需要与子系统内部的很多对象打交道。 外观模式的目的在于降低系统的复杂程度。 外观模式从很大程度上提高了客户端使用的便捷性,使得客户端无须关心子系统的工作细节,通过外观角色即可调用相关功能。

优点:

主要优点在于对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易,它实现了子系统与客户之间的松耦合关系,并降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程;

缺点:

其缺点在于不能很好地限制客户使用子系统类,而且在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。

使用情况:

适用情况包括:要为一个复杂子系统提供一个简单接口;客户程序与多个子系统之间存在很大的依赖性;在层次化结构中,需要定义系统中每一层的入口,使得层与层之间不直接产生联系。

python-外观模式的更多相关文章

  1. 研磨设计模式解析及python代码实现——(二)外观模式(Facade)

    一.外观模式定义 为子系统中的一组接口提供一个一致的界面,使得此子系统更加容易使用. 二.书中python代码实现 class AModuleApi: def testA(self): pass cl ...

  2. Python设计模式之"外观模式"实例讲解

    Python中设计模式之外观模式主张以分多模块进行代码管理而减少耦合,下面用实例来进行说明. 应用特性: 在很多复杂而小功能需要调用需求时,而且这些调用往往还有一定相关性,即一调用就是一系列的. 结构 ...

  3. 大话设计模式Python实现-外观模式

    外观模式(Facade Pattern):为子系统中的一组接口提供一个一致界面,此模式定义一个高层接口,使得子系统更加容易使用 下面是一个外观模式的demo: #!/usr/bin/env pytho ...

  4. 浅谈Python设计模式 - 外观模式

    声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 外观模式 外观模式的核心在于将复杂的内部实现包装起来,只向外界提供简单的调用接口 ...

  5. python设计模式之外观模式

    python设计模式之外观模式 系统会随着演化变得非常复杂,最终形成大量的(并且有时是令人迷惑的)类和交互,这种情况并不少见.许多情况下,我们并不想把这种复杂性暴露给客户端.外观设计模式有助于隐藏系统 ...

  6. Python设计模式——外观模式

    外观模式跟代理模式有点像,都是在client和目标的类之间建一个中间的类,client不直接调用目标的类,而是通过先调用中间类的方法,由中间类来实现怎么调用目标类. 代理模式用这种模式的目的是可以实现 ...

  7. [Python设计模式] 第12章 基金理财更省事——外观模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟股民直接炒股的代码,比如股民投资了股票1,股票2,股票3,国债 ...

  8. python : 设计模式之外观模式(Facade Pattern)

    #为啥要用外观模式举例说明 这个例子很形象,直接从人家博客上贴过来的,参考链接在下面 不知道大家有没有比较过自己泡茶和去茶馆喝茶的区别,如果是自己泡茶需要自行准备茶叶.茶具和开水,如图1(A)所示,而 ...

  9. Python设计模式(9)-外观模式

    # /*外观模式:为外界调用提供一个统一的接口,把其他类中需要用到的方法提取# * 出来,由外观类进行调用.然后在调用段实例化外观类,以间接调用需要的# * 方法.这种方式和代理模式有异曲同工之妙.然 ...

  10. 使用C# (.NET Core) 实现适配器模式 (Adapter Pattern) 和外观模式 (Facade Pattern)

    本文的概念内容来自深入浅出设计模式一书 现实世界中的适配器(模式) 我带着一个国标插头的笔记本电脑, 来到欧洲, 想插入到欧洲标准的墙壁插座里面, 就需要用中间这个电源适配器. 面向对象的适配器 你有 ...

随机推荐

  1. (干货) Android实现ImageVIew多点触控及双击缩放

    支持多点触控,放大自由移动,双击可以放大缩小.直接上代码: package com.cbt.view; import android.content.Context; import android.g ...

  2. 装饰器中的@functools.wraps的作用

    def login_required(view_func): @functools.wraps(view_func) def wrapper(*args, **kwargs): ...... retu ...

  3. [原创]K8 DNN密码解密工具(DotNetNuke Password Decrypt)

    工具: K8_DNN_Password_Decrypt编译: VS2012  C# (.NET Framework v2.0)组织: K8搞基大队[K8team]作者: K8拉登哥哥博客: http: ...

  4. Vue2.5开发去哪儿网App 城市列表开发之 兄弟组件间联动及列表性能优化

    一,  兄弟组件间联动 1.  点击城市字母,左侧对应显示 给遍历的 字母 添加一个点击事件: Alphabet.vue @click="handleLetterClick" ha ...

  5. linux 下NFS远程目录挂载

    NFS 是Network File System的缩写,中文意思是网络文件系统.它的主要功能是通过网络(一般是局域网)让不同的主机系统之间可以共享文件或目录.NFS客户端(一般为应用服务器,例如web ...

  6. Spring4 mvc+maven 框架搭建(3)

    经过前面两个环节,spring mvc的原料已经准备好了,现在就可以正式开始搭建springmvc框架了. 首先先介绍介绍搭建的框架具有的功能: 1)集成log4j,配置好日志相关并可以打印出相关的日 ...

  7. C#:使用ListView动态添加数据一直闪烁的解决办法

    首先,自定义一个类ListViewNF,继承自 System.Windows.Forms.ListView using System; using System.Collections.Generic ...

  8. Selenium之元素定位

    1.查看页面元素:ID.class.type.name等. 2.通过webdriver的方法定位: find_element_by_name()  find_element_by_id()  find ...

  9. chrome版本与对应的chromedriver驱动【转载】

    chrome版本与对应的谷歌驱动(chromedriver) 1.下载chromedriver:http://chromedriver.storage.googleapis.com/index.htm ...

  10. java工具类-日期工具类

    1.获得时间戳 为了统一其他语言的如php和unix系统获取的时间戳是10位长度的,精确到秒. java时间戳长度是13位,精确到毫秒 我们获取时间戳需要相应处理. //获取当前时间戳,除以1000, ...