资讯专栏INFORMATION COLUMN

写代码也有“套路”-谈谈设计模式

tain335 / 2177人阅读

摘要:所以设计模式其实就是在前人各种踩坑经验之上,总结出的各种开发套路。但更好的套路是使用单例模式它可以保证只创建一个对象第一次访问时创建,之后访问时直接返回已有对象,并提供全局的访问。因此也有很多人对于设计模式的价值存在质疑。

编程教室开了这么久,已经有很多人从完全零基础的小白成为了会写代码的菜鸟程序员,能够自己独立开发程序。不过到此阶段,常常会遇到瓶颈,感觉功能可以实现,但代码看起来有些别扭:

代码中有很多相似的重复代码

代码中有大量的 if,以至于有很长的缩进

单个代码写得很长,别人很难看懂,过阵子可能自己都看不懂

总会有没有考虑到的情况导致 bug

修复一个 bug 又会产生新的 bug

单个功能可以实现,但多个功能组合在一起就理不清

如果需求发生变动,代码修改起来很麻烦

有多种实现方式时不知道该用哪一种

很难和其他人协作开发

上述的问题你是不是有过类似困扰?解决的办法其实也简单,就是坚持“ 多写 ”和“ 多读 ”:

多写代码。很多时候你觉得不好处理,并不是因为高深的问题,只是你对代码的基本使用还不够熟练。同样的问题,踩过坑再爬出来,反复几次自然你也知道怎么绕开了。

多读代码。除了自己写,看看别人的代码也会学到很多。包括教程里的案例、官方示例、开源项目的源码等。所谓“熟读唐诗三百首,不会作诗也会吟”嘛。

除了这两个“笨办法”外,还有样东西,对于处在这个阶段的你或许有很大启发,这就是:

设计模式

设计模式是对于软件开发中常见的一些问题所总结出的解决方案,它并不关注具体的代码怎么写,而是 代码的结构应该如何设计 ,从而让代码 更加可靠、可读、可重用、易于维护 。它不是一种严格意义上的“技术”,而是一门“经验主义”,也就是开发者经常提到的“ 最佳实践 ”。所以设计模式其实就是在前人各种踩坑经验之上,总结出的各种开发“套路”。

举几个常见的设计模式例子:

单例模式

场景举例:代码中需要一个共享的资源管理器,保证在代码只有唯一的一个实例,且代码各处都可以访问到。

如果你的代码只有一个文件,可能不会遇上这个问题。但当项目大一点之后,这个问题十分常见。你可以选择定义一些全局变量来实现。但更好的“套路”是使用单例模式:它可以保证 只创建一个对象 (第一次访问时创建,之后访问时直接返回已有对象), 并提供全局的访问

代码演示


# 单例类
class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kw):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
        return cls._instance

# 继承单例
class MyClass(Singleton):  
    a = 1

# 使用
mc1 = MyClass()
mc2 = MyClass()
print(mc1==mc2)
mc1.a += 1
print(mc2.a)

输出


True
2

之前我们的文章《Crossin:Python单例模式(Singleton)的N种实现》有专门讨论过 Python 中的单例模式实现。

工厂模式

场景举例:在一个绘图工具里,有不同的笔刷。当点击不同的笔刷按钮时,需要创建对应的笔刷供使用。

如果把每个按钮响应里都去多带带创建,代码会很冗余且不利于维护。这时可创建一个“工厂”类,将创建笔刷的代码放在其中, 只需要根据传入的参数不同,返回不同的笔刷实例即可 。就如同工厂根据订单生产产品一样。

代码演示


# 笔刷工厂,具体类代码略
def pen_factory(mode):
    if mode == "PEN":
        return Pen()
    elif mode == "PENCIL":
        return Pencil()
    elif mode == "BRUSH":
        return Brush()
    else:
        return None

# 使用
p = pen_factory("BRUSH")

代理模式

场景举例:开发一个论坛,允许用户在帖子中上传图片,于是需要提供保存图片的功能。

一般为了网站的访问速度,会选择第三方的图片保存服务。那么在保存图片的时候,就需要调用其提供的接口。而应用代理模式的话,就会在网站和第三方服务间增加一层。这样的好处是可以 将一些额外的处理放在代理层中 ,当需要更换第三方服务时, 不需要修改网站的逻辑 ,只要调整代理层即可。

代码演示


class ImgService:
    @abstractmethod
    def save(self, img):
        pass

# 真实类
class XYZImgService(ImgService):
    def save(self, img):
        # 调用第三方服务接口

# 代理类
class ImgServiceProxy(ImgService):
    def __init__(self):
        self.service = XYZImgService()
    def save(self, img):
        return self.service.save(img)

# 使用
def save_img(img):
    proxy = ImgServiceProxy()
    proxy.save(img)

设计模式的 六大原则

1、 开闭原则 (Open Close Principle)
对扩展开放,对修改关闭。在需求变动时,尽可能不修改原有代码,而通过扩展实现。

2、 里氏代换原则 (Liskov Substitution Principle)
在使用继承时,在子类中尽量不要重写和重载父类的方法。

3、 依赖倒转原则 (Dependence Inversion Principle)
针对接口编程,细节依赖于抽象。

4、 接口隔离原则 (Interface Segregation Principle)
降低类之间的耦合度,不依赖不必要的接口。

5、 迪米特法则 ,又称 最少知道原则 (Demeter Principle)
模块之间相互独立,对自己依赖的类需要知道的信息越少越好。

6、 合成复用原则 (Composite Reuse Principle)
尽量使用合成/聚合的方式,而不是使用继承。

具体的解读,今天没法在一篇推送中展开详述,而且这是个需要不断体会和实践的事情。首先你可以找些相关书籍读一读。设计模式有一本经典书籍:《 Design Patterns: Elements of Reusable Object-Oriented Software 》(《设计模式:可复用面向对象软件的基础》)。此书又被称作“ GoF ”(Gang of Four,四人组),四位业内大牛总结出了 23 种设计模式。

然而,我强烈 推荐新手去看这本书,因为你很可能看不懂。我推荐的是一本叫做《 Head first 设计模式 》的书,可以算作上面那本的白话入门版,对于新手来说友好许多,或许帮助更大。

开发者对于设计模式的理解大致存在这样几个阶段:一开始只关注语法和库, 不懂设计模式 ,写代码无章法;后来了解了设计模式之后,开始尝试 套用设计模式 ,懂得重构代码,但有时难免教条化或陷入过度设计的误区;等到开发经验丰富之后, 不再拘泥于所谓的“模式” ,本身写出的代码就已经契合设计的原则。

书上的设计模式是一成不变的,不可能涵盖每一种开发场景,而软件技术本身也不断发展,很多模式已经被新的语言特性所实现。因此也有很多人对于设计模式的价值存在质疑。我的看法是,如果你处在新手阶段, 学习设计模式是很好的提升方式 ,也可以开拓你的编程思维。而当你已经走上进阶之路之后, 更多的应是关注模式背后的原则 ,写出更合理的代码,而并非为了模式而模式。

当然这一切,还是都离不开足够的代码量。每个程序员都是一行行代码堆出来。

════

其他文章及回答:

学编程:如何自学Python | 新手引导 | 一图学Python

开发案例:智能防挡弹幕 | 红包提醒 | 流浪地球

欢迎搜索及关注: Crossin的编程教室

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/43238.html

相关文章

  • 编程中的那些套路——关于观察者模式

    摘要:我们应该写一段拓展性强与维护性较强的代码,由此衍生出观察者模式。 该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 今天我们来谈谈观察者模式,这是一个经常用到的设计模式。 让我们想象一个场景:一个网站有不同等级区域的用户,不同等级的的用户登录后可以获得对应的服务(一级用户登录后获得一级服务,二级用户登录后获得二级服务,…以此类推)。那么我们如何写这段业...

    Fourierr 评论0 收藏0
  • 编程中的那些经典套路——设计模式汇总

    摘要:如果看不懂的话,可以在评论区中提问,我会第一时间回答你无论何时我一直都在嗯哼该文章属于编程中的那些经典套路设计模式汇总系列 在正式阅读前,我先谈谈我们该用什么姿势和心态学习设计模式: 如果你还没有过多的编程经验(泛指半年以下),我建议你把它当做小说来看,能看懂多少是多少,因为半年以下经验的程序员用到设计模式的情况只会出现在面试上,至于实际工作中?相对来说这部分不会由你负责。 如果你已...

    youkede 评论0 收藏0
  • 编程中的那些套路——关于适配器模式

    该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 今天我们来谈谈适配器模式。 想象一个场景: 有一个类方法它部署在服务器上,专门负责大多数语言都通用的JSON语言,而现在我需要调用这个类方法,但我不需要返回JSON格式的数据了,我要返回序列化后的数据,我现在如何处理呢?是上去服务器修改这个类方法吗?这不科学吧?因为我们原本编写好的代码最好就不要再改了,很容易造成...

    gnehc 评论0 收藏0
  • 编程中的那些套路——关于装饰器模式

    该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 今天我们来谈谈装饰器模式,想象一个场景: 有一篇帖子 帖子的内容我写好了, 三个部门的人员想控制它. 编辑组要添导读文字 审核组要去敏感字 市场部想在末尾加点广告 我只是一篇帖子,由你们来处置吧。 此时如何处理呢?如何写出符合面向对象三特性五原则的代码呢?由此引出装饰器模式就发挥作用了 一言不合来看看代码: 装...

    lavor 评论0 收藏0
  • 编程中的那些套路——关于责任链模式

    该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 今天来谈谈责任链模式,乍一听责任链模式好像很高级的一样,但是相信我,其实每位天朝的同学都十分熟悉这个模式,责任链模式,就好像中国的官场制度一样,每一个级别的权利都区分的很细,举个生活中的栗子: 村委不能越级去替镇委办事情,如果村委无法解决,只能向上求助镇委 镇委不能越级去替市委办事情,如果镇委无法解决,只能向上求...

    lylwyy2016 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<