首页 > 其他分享 >设计模式及设计规则详解(1)

设计模式及设计规则详解(1)

时间:2022-12-08 17:34:31浏览次数:56  
标签:__ self 用户 工厂 详解 video 规则 设计模式 def

设计模式

什么是设计模式?

是在系统设计中针对场景的一种方案,是解决功能逻辑开发的一种共性问题

设计模式学习的是什么?

学习的是设计模式的思想,不能直接进行硬套

设计原则

  1. 单一职责原则(单一功能原则):每一个类中应该只有一个发生变化的原因,每个类中只实现一个功能。
  • 模拟场景

    视频网站不同的用户看视频的效果是不一样的,用户可分为访客用户、普通用户、vip客户等,例如访客用户只能看到480p的视频,vip用户可以看到2k视频等,下面进行最普通的实现。

    class VideoService(object):
        def __init__(self) -> None:
            pass
    
        def WatchVideo(self, user_type):
            if user_type == "访客用户":
                print("480p")
            elif user_type == "普通用户":
                print("720p")
            elif user_type == "VIP用户":
                print("1080p")
    

    测试代码如下

    from base import VideoService
    
    
    if __name__ == "__main__":
        video = VideoService()
        video.WatchVideo("访客用户")
        video.WatchVideo("普通用户")
        video.WatchVideo("VIP用户")
    
    480p
    720p
    1080p
    

    上述使用了最基础的if else方法,通过用户类型进行逻辑调用,变化的点目前只有传入的用户类型,实现的功能包含用户的类型区分以及不同用户观看视频的处理逻辑两个功能。

    突然有一天,需要对不同的用户做观看广告的区分,使用if else方法时,则需要对每一层if else中做处理,此时,变化的点为传入的用户类型以及不同用户类型的处理逻辑,不符合单一职责原则,并且如果if else比较多的话,代码的可维护性就会降低很多。

    因此可以遵循单一职责原则,将不同用户的视频处理逻辑分别基于抽象类或者基类生成不同的用户视频处理类,当有地方需要使用时,只需要调用对应的用户类即可,并且当某个用户的行为发生变化时,只需要修改对应的类即可。修改如下:

    基类: 用于提供实现不同用户类方法

    class VideoService(object):
        def definition(self):
            """清晰度"""
            pass
    
        def advertisement(self):
            """广告"""
            pass    
    

    不同用户的实现类

    from video_service import VideoService
    
    
    class VistorVideoService(VideoService):
        def definition(self):
            print("48p")
    
        def advertisement(self):
            print("30s广告")
    
    from video_service import VideoService
    
    
    class NormalVideoService(VideoService):
        def definition(self):
            print("720p")
    
        def advertisement(self):
            print("10s广告")
    
    from video_service import VideoService
    
    
    class VipVideoService(VideoService):
        def definition(self):
            print("1080p")
    
        def advertisement(self):
            print("无广告")
    
    

    测试类

    from vistor_video_service import VistorVideoService
    from normal_video_service import NormalVideoService
    from vip_video_service import VipVideoService
    
    if __name__ == "__main__":
        vistor = VistorVideoService()
        vistor.definition()
        vistor.advertisement()
        normal = NormalVideoService()
        normal.definition()
        normal.advertisement()
        vip = VipVideoService()
        vip.definition()
        vip.advertisement()
    
    48p
    30s广告
    720p   
    10s广告
    1080p  
    无广告 
    

    上述的用户类分别只复杂一个用户类型的功能,符合单一职责原则,当需要进行部分用户规则修改的时候,只需修改对应的用户类中的逻辑即可。

  • 总结

    单一职责原则适用于同一种事物的不同类型会导致的不同的结果,例如用户登录时不同用户的权限控制。

  1. 开闭原则: 对扩展开放,对修改关闭。
  • 模拟场景

    假设我们需要计算正方形、圆形等面积,目前我们需要提供一个sdk或者说是模块提供圆形的面积计算。基类如下:

    class CircularCompute(object):
        def __init__(self) -> None:
            self.pai = 3.14
    
        def compute_circular(self, r):
            return self.pai * r * r
    

    当不同用户的使用时,圆形的面积默认情况下是派r平方,但是派又有不同的精度,可能不同人使用需要的精度不一样,可以继承此基类修改pai的精度重新进行计算,如下:

    from circular_compute import CircularCompute
    
    
    class Extend_Compute(CircularCompute):
        def __init__(self) -> None:
            super().__init__()
            self.pai = 3.1415926
    
        def compute_circular(self, r):
            return super().compute_circular(r)
    # 测试
    if __name__ == "__main__":
        compute = Extend_Compute()
        ret = compute.compute_circular(2)
        print(ret)
    

    上述继承自计算面积类,并重新设置了派的值,这样不同用户之间的调用就不会相互影响了。

  • 总结

    开闭原则规定了提供的sdk或者说是模块,当用户使用时,只能基于已有sdk做扩展,而无法直接修改其中的源码,保证了sdk或模块的独立性,从而尽可能地保证sdk或者模块地通用性,此原则个人理解是想尽可能地提高代码的可复用性、通用性,因此适用于代码需要复用或者说是通用的情况,对于一些内部逻辑或者较少使用的情况,不建议再基于基类进行继承扩展。

工厂模式

是创建型模式,在父类中提供创建对象的方法,允许子类决定实例化对象。工厂返回的是实例对象,只是实例对象可能是由不同的子类去实例化的。工厂模式,又分为简单工厂模式、工厂方法模式、抽象工厂模式。

  • 模拟场景

    此处使用上述单一职责原则示例,用户最终的动作都是查看视频,不同用户的动作均是基于基类实现,此时,当我们需要进行不同用户权限的逻辑时,可以使用如下代码:

    • 简单工厂模式
    from normal_video_service import NormalVideoService
    from vip_video_service import VipVideoService
    from vistor_video_service import VistorVideoService
    
    
    class CreateFactory(object):
        def createVideoService(self, user_type):
            if user_type == "访客用户":
                return VistorVideoService()
            elif user_type == "普通用户":
                return NormalVideoService()
            elif user_type == "VIP用户":
                return VipVideoService()
            else:
                return None
    

    创建了一个工厂类,返回不同用户的实例化对象,上述使用的是最基础的if else方法依据不同的用户类型实例化不同的对象,当然我们也可以将不同的实例对象与用户类型定义为一个字典,通过字典的获取方式去获取。
    UML图如下:
    image

    优点:将对象的创建交由工厂去创建,实现了对象的创建与对象的实现的分离

    缺点:不够灵活,当我们需要去新增具体的类型时,需要修改原有的工厂类,添加一个if else判断,并且当产品的类型比较多时,如果使用if else,维护起来会比较麻烦,当然也可以通过一个公共的字典去维护这些。

    下面将简单使用字典来替换if else,代码如下:

    user_video_dict = {
        "访问用户": VistorVideoService(),
        "普通用户": NormalVideoService(),
        "VIP用户": VipVideoService(),
    }
    
    
    class CreateFactoryExtend(object):
        def createVideoService(self, user_type):
            return user_video_dict.get(user_type, None)
    
    

    当有新的产品时,可以添加到字典中,无需再手动修改工厂类。

    • 工厂方法模式

    需要创建一个抽象工厂类或者说是基类,相比较简单工厂模式,需要为不同的产品分别创建工厂(基于抽象工厂类),一个工厂只会产生一种产品

    还是基于上述的单个职责原则的示例,需要创建一个基类工厂,之后为不同的用户视频操作类创建不同的工厂,代码如下:

    # 基础工厂类
    class BaseFactory(object):
        def createFactory(self):
            pass
    
    # 访客用户工厂类
    from base_factory import BaseFactory
    from vistor_video_service import VistorVideoService
    
    
    class VistorFactory(BaseFactory):
        def createFactory(self):
            return VistorVideoService()
    
    # 普通用户工厂类
    from base_factory import BaseFactory
    from normal_video_service import NormalVideoService
    
    
    class NormalFactory(BaseFactory):
        def createFactory(self):
            return NormalVideoService()
    
    # vip用户工厂类
    from base_factory import BaseFactory
    from vip_video_service import VipVideoService
    
    
    class VipFactory(BaseFactory):
        def createFactory(self):
            return VipVideoService()
    
    

    当使用时只需要调用对应的工厂类返回对应的实例对象即可,代码如下:

    from normal_factory import NormalFactory
    
    
    if __name__ == "__main__":
        # 创建工厂
        normal_factory = NormalFactory()
        # 创建实例化对象
        obj = normal_factory.createFactory()
        obj.definition()
        obj.advertisement()
    
    720p
    10s广告
    

    UML图如下:
    image

    优点: 符合开闭原则,当需要新增产品时,直接基于工厂基类创建新的工厂类即可,当然,工厂类中不同对象类也需要实现
    缺点: 当需要新增产品的数量较多时,会出现较多的工厂类

    • 抽象工厂模式

    前面说到,工厂方法模式是一个工厂生产一种产品,抽象工厂则是一个工厂可以生产两种及多种产品。此处暂时搁置

重点

工厂模式必须要有工厂对象、产品基类/抽象产品类、具体的产品类(基于产品基类)、工厂基类/抽象工厂类(只会出现在工厂方法模式和抽象工厂模式), 简单工厂模式UML示意图如下:
image

需要注意的是工厂模式最终返回的是实例对象,工厂方法类似这么一个场景:有一个盒子,其中存放了很多大小一致的球,用户根据自己的选择拿取其中的一个球,然后可以拿球去兑奖;盒子相当于是工厂对象,球相当于是具体的产品类,球对应的兑换的产品则相当于是具体产品类中的逻辑,大小一致的球表明是按照一个特定的球去设计的,那个特定的球相当于是产品基类。

适用场景

  • 需依赖不同环境创建不同的实例,且实例具有相同的行为,例如上述描述的不同用户的权限访问、抽奖时的不同奖品(实物、虚拟卡券等)。
  • new操作的简单封装,依据不同的环境获取不同的实例对象。

标签:__,self,用户,工厂,详解,video,规则,设计模式,def
From: https://www.cnblogs.com/xy-bot/p/16966709.html

相关文章

  • MYSQL-INNODB索引构成详解
    作者:郑啟龙摘要:对于MYSQL的INNODB存储引擎的索引,大家是不陌生的,都能想到是B+树结构,可以加速SQL查询。但对于B+树索引,它到底“长”得什么样子,它具体如何由一个个字节构成的,......
  • 嵌入式:ARM系列处理器详解与性能对比
    ARM处理器目前包括以下几个系列:ARM7系列ARM9系列ARM9E系列ARM10E系列SecurCore系列Inter的XscaleInter的StrongARM其中,ARM7、ARM9、ARM9E和ARM10为4个通用处理器系列,每一个......
  • 一、基础折线图详解《手把手教你 ECharts 数据可视化详解》
    注:本系列教程需要对应JavaScript、html、css基础,否则将会导致阅读时困难,本教程将会从ECharts的官方示例出发,详解每一个示例实现,从中学习ECharts。ECharts官方示例:h......
  • ipsec详解
    ​IPSec(互联网协议安全)是一个安全网络协议套件,用于保护互联网或公共网络传输的数据。IETF在1990年代中期开发了IPSec协议,它通过IP网络数据包的身份验证和加密来提供I......
  • ThreadLocal 详解
    ThreadLocal详解ThreadLocal简介ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量......
  • 详解从无人机倾斜实景三维建模→模型修复→成果网络发布展示分享全流程
    工具软件:1、倾斜实景三维建模软件:CC(Smart3D)软件2、实景三维模型网页在线发布展示、分享平台:图新地球网页端(Wish3D·Earth平台) 图新地球网页端(Wish3D·Earth平台)是基......
  • iOS app上架app store流程详解​
     前提条件​在有效期内的苹果开发者账号(类型为个人或者公司账号)。还有一种情况,就是你的AppleID被添加到公司开发者账号团队里面,这样也是可以的,但是需要叫管理员给你开......
  • 模拟地与数字地详解
    转自https://blog.csdn.net/kevinhg/article/details/12080751 二者本质是一直的,就是数字地和模拟地都是地。要明白为什么要分开,先听一个故事;我们公司的商务楼,2楼是搞......
  • 提升规则自治能力与原生分析能力、支持视频流接入处理
    11月,​​eKuiper​​团队转入1.8.0版本的开发周期之中,目前已完成了一部分实用的新功能:添加了视频流source,将边缘流式处理能力扩展到视频流领域,可以处理摄像头的视频流......
  • iOS AppStore上架流程图文详解​
     1、首先得注册AppleDeveloper的开发者账号,最后如果要上架苹果商店,这个账号是要交年费的,核算下来大概600多元人民币。​2、接下来要登录AppleDeveloper网站,点击“Acco......