开放封闭原则

开放封闭原则

面向对象原则
在面向对象的设计中有很多流行的思想,比如"所有的成员变量都应该设置为私有(python中使用__定义私有属性)","要避免使用全局变量"等等。这些思想的源泉就来自于面向对象的六大原则,分别为单一职责原则、开放封闭原则、依赖倒置原则、接口隔离原则、里氏替换原则、迪米特法则。
开放封闭原则描述
符合开放封闭原则的模块都有两个主要特性:
    1.面向扩展开放(Open For Extension)
    也就是说模块的行为是能够被扩展的。当应用程序的需求变化时,我们可以使模块表现出全新的或与以往不同的行为,以满足新的需求。
    2.面向修改封闭(Closed For Modification)
    模块的源代码是不能被侵犯的,任何人都不允许修改已有源代码。

看起来上述两个特性是互相冲突的,因为通常扩展模块行为的常规方式就是修改该模块。一个不能被修改的模块通常被认为其拥有着固定的行为。那么如何是这两个相反的特性共存?就是使用抽象

本人也是在学习java的过程中认识到抽象的概念,java是面向对象最典型的语言,java崇尚面向接口编程,而这个接口其实就是一个抽象出来的类,其中拥有很多抽象方法,(为什么布面向抽象类编程,可能是因为java只能单继承,但是可以实现多个接口),而python中没有抽象的具体概念,当然也是有实现抽象的办法。

1.方式一:抛出NotImplementedError异常

class SuperClass(object):
    def eat(self):
        print('父类吃')
    
    def display(self):
        raise NotImplementedError('子类必须实现或重写该方法')

class SubClass(SuperClass):
    def display(self):
        print('子类的display方法')

2.使用元类(metaclass,元类的概念就非常抽象)

python3版本

from abc import ABCMeta,abstractmethod
class SuperClass(metaclass=ABCMeta):
    def eat(self):
        print('父类吃')
        
    @abstractmethod   
    def display(self):
        pass
   
class SubClass(SuperClass):
    def display(self):
        print(子类必须实现的display方法)

python2版本

from abc import ABCMeta,abstractmethod
class SuperClass:
    __metaclass__ = ABCMeta
    
    def eat(self):
        print('父类吃')
        
    @abstractmethod   
    def display(self):
        pass
   
class SubClass(SuperClass):
    def display(self):
        print(子类必须实现的display方法)

生活中简单的抽象:

自然界中很许多的动物,他们都有各自的特性,但是也有很多的共性,我们将共性抽取出来,生成一个Animal的抽象类,其中具有抽象方法eat(),run()等这些所有动物都具有的共性,这个类就作为其他所有动物的超类,而他们都必须在继承该类后重写这些抽象方法,Animal类不会再去修改,也就是面向修改封闭,而继承他的子类会根据自己的特性在进行扩展,这就是面向扩展开放。
Django中的开放封闭

其实我们在使用Django的时候也不难发现其中运用到的开放封闭原则,最好的案例就是Django的settings文件。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

这是settings文件中配置中间件的部分,我们不需要使用某个中间件时,只需要将其注释,而不是去删除该中间件模块,我们自定义中间件,只需要在MIDDLEWARE列表的合适位置添加自定义中间件的路径就可以了,这就是在不改变源代码的情况下实现了功能的扩展。

在Flask中实现类似功能

说明:发送消息的方式有很多种,如邮件,短信推送,微信推送等,所以我们模仿Django的MIDDLEWARE也来实现以下发送信息的模块。

settings.py

MSG_LIST = [
    'message.msg.Msg',
    'message.email.Email',
]

message下的base.py(抽象类)

class Base(object):
    def send(self,msg):
        raise NotImplementedError('... ')

message下的msg.py

from .base import Base
class Msg(Base):
    def __init__(self):
        self.username = 'ss'
        self.pwd = 'aksjf'

    def send(self):
        print('msg_send')

message下的email.py

from .base import Base
class Email(Base):
    def __init__(self):
        self.username = 'ss'
        self.pwd = 'aksjf'

    def send(self):
        print('email_send')

我们在message模块的__init___下进行编写

import settings
import importlib


def send_msg(msg):
    for item in settings.MSG_LIST:
        m, c = item.rsplit('.', maxsplit=1)
        md = importlib.import_module(m)
        cls = getattr(md, c)()
        cls.send()

app中使用

from flask import Flask
from message import send_msg
app = Flask(__name__)

@app.route('/')
def index():
    # 比如这里需要使用到发送消息
    send_msg('some message')
    return 'index 页面'

如果我们只需要使用短信推送,我们就可以将settings文件中的message.email.Email注释,如果有添加微信推送功能,我们也只需要在添加一行文件路径就可以了,当然这只是个案例,也许不符合现实生活的需要。

总结
要明白程序是不可能100%完全封闭的,无论模块的设计有多封闭,总是有各种各样的变化来打破这种封闭,所以需要讲究策略来实现封闭。

转载于:https://www.cnblogs.com/louyefeng/p/10925652.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值