美文网首页我爱编程
【设计模式】【结构型模式】外观模式

【设计模式】【结构型模式】外观模式

作者: flowerAO | 来源:发表于2018-05-27 13:04 被阅读0次

    系统会随着演化变得非常复杂,最终形成大量的(并且有时是令人迷惑的)类和交互,这种情况并不少见。许多情况下,我们并不想将这种复杂性暴露给客户端。外观设计模式有助于隐藏内部的复杂性,并通过一个简化的接口向客户端暴露必要的部分。本质上,外观(Facade)是在已有复杂系统之上实现的一个抽象层。
    使用外观模式的最常见的理由是为一个复杂 系统提供单个简单的入口点。引入外观之后,客户端代码通过简单地调用一个方法就能使用一个系统。同时,内部系统并不会丢失任何功能,外观只是封装了内部系统。
    如果你的系统包含多层,外观模式也能派上用场。你可以为每一层引入一个外观入口点,并让所有层级通过它们的外观相互通信。这提高了层级之间的松耦合性,尽可能保持层及独立。

    实现

    假设我们想使用多服务进程方式来实现一个操作系统。多服务进程的操作系统有一个极小的内核,称为 微内核,它在特权模式下运行。系统的所有其他服务都遵从一种服务架构(驱动程序服务器、进程服务器、文件服务器等)。每个服务进程属于一个不同的内存地址空间,以用户模式运行在微内核之上。这种方式的优势是操作系统更能容错、更加可靠、更加安全。例如,由于所有的驱动程序都以用户模式在一个驱动服务进程之上运行,所以某个驱动程序中的一个bug并不能使整个系统崩溃,也无法影响到其他的无父进程。其劣势是性能开销和系统编程的复杂性,因为服务进程和微内核之间,还有独立的服务进程之间,使用消息传递方式进行通信。消息传递比宏内核所使用的共享内存模式更为复杂。

    我们从server接口(这里的接口并不是指Interface,而是指一个不能直接实例化的类。)开始实现,使用一个Enum类型变量来描述一个服务进程的不同状态,使用abc模块来禁止对server接口直接进行初始化,并强制子类实现关键的boot()和kill()方法。这里假设每个服务进程的启动、关闭及重启都相应地需要不同的动作。如果你以前没有用过abc模块,请记住以下几个重要事项。

    • 我们需要使用metaclass关键字来继承ABCMeta
    • 使用@abstractmethod修饰器来声明Server的所有子类都强制性的应该实现哪些方法
      尝试移除一个子类方法,看看会发生什么。移除@abstractmethod修饰器之后再试试。
    # /usr/bin/python
    # coding:utf-8
    
    from abc import ABCMeta, abstractmethod
    from enum import Enum
    
    State = Enum('State', 'new running sleeping restart zombine')
    
    
    class Server(metaclass=ABCMeta):
        @abstractmethod
        def __init__(self):
            pass
    
        def __str__(self):
            return self.name
    
        @abstractmethod
        def boot(self):
            pass
    
        @abstractmethod
        def kill(self, restart=True):
            pass
    
    
    class FileServer(Server):
        def __init__(self):
            '''初始化文件服务进程要求的操作'''
            self.name = 'FileServer'
            self.state = State.new
    
        def boot(self):
            '''启动文件服务进程要求的操作'''
            print('booting the {}'.format(self))
            self.state = State.running
    
        def kill(self, restart=True):
            '''终止文件服务进程要求的操作'''
            print('Killing {}'.format(self))
            self.state = State.restart if restart else State.zombine
    
        def create_file(self, user, name, permissions):
            '''检查访问权限的有效性和用户权限等'''
            print('trying to create the file "{}" for user "{}" with permissions {}'.format(name, user, permissions))
    
    
    class ProcessServer(Server):
        def __init__(self):
            '''初始化进程服务进程要求的操作'''
            self.name = 'ProcessServer'
            self.state = State.new
    
        def boot(self):
            '''启动进程服务进程要求的操作'''
            print('booting the {}'.format(self))
            self.state = State.running
    
        def kill(self, restart=True):
            '''终止进程服务进程要求的操作'''
            self.state = State.restart if restart else State.zombine
    
        def create_process(self, user, name):
            '''检查用户权限和生成PID等'''
            print("trying to create the process '{}' for user '{}'".format(name, user))
    
    
    class OperatingSystem:
        '''外观'''
    
        def __init__(self):
            self.fs = FileServer()
            self.ps = ProcessServer()
    
        def start(self):
            [i.boot() for i in (self.fs, self.ps)]
    
        def create_file(self, user, name, permissions):
            return self.fs.create_file(user, name, permissions)
    
        def create_process(self, user, name):
            return self.ps.create_process(user, name)
    
    
    def main():
        os = OperatingSystem()
        os.start()
        os.create_file('fool', 'hello', '-rw-r-r')
        os.create_process('bar', 'ls /tmp')
    
    
    if __name__ == '__main__':
        main()
    
    

    输出

    booting the FileServer
    booting the ProcessServer
    trying to create the file "hello" for user "fool" with permissions -rw-r-r
    trying to create the process 'ls /tmp' for user 'bar'
    
    Process finished with exit code 0
    
    

    在客户端想要一个复杂系统但又不关心系统的复杂性之时,这种模式是为复杂系统提供一个简单接口的理想方式。一台计算机是一个外观,因此当我们使用它时需要做的事情仅是按一个按钮来启动它;其余所有硬件复杂性都用户无感知地交给BIOS、引导家在程序以及其他系统软件来处理。现实生活中外观例子更多,比如,我们所致电的银行或公司客服部门,还有启动机动车所使用的钥匙。
    外观是一种隐藏系统复杂性的优雅方式,因为多数情况下客户端代码并不应该关心系统的这些细节。

    遗留问题

    • python的抽象子类如何调用父类的属性以及方法?
    • python的父类init也为抽象方法的时候,如何在子类中进行运用?
    • 存根是什么

    相关文章

      网友评论

        本文标题:【设计模式】【结构型模式】外观模式

        本文链接:https://www.haomeiwen.com/subject/kxnmjftx.html