• 软件构造:面向可复用性和可维护性的设计模式


        在我们写完一份软件之后,我们往往需要对这份软件进行后续的更新与维护,同时我们也希望在后续的软件编写的过程中利用到之前编写的内容,进行软件的服用。因此,本片聚焦于几种面向可复用性和可维护性的设计模式,介绍设计的几种方法。
    一、创建型模式:

    1.工厂方法模式:

        工厂方法模式由抽象工厂、具体工厂、抽象产品和具体产品等4个要素构成。抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。抽象产品:定义了产品的规范,描述了产品的主要特性和功能。具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

        优点:

            a.用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。

            b.灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。

            c.典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。

        缺点:

            a.类的个数容易过多,增加复杂度

            b.增加了系统的抽象性和理解难度

            c.抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。

        应用场景:

            a.客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。

            b.创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。

            c.客户不关心创建产品的细节,只关心产品的品牌

    二、结构型模式:

    1.适配器模式:

        适配器模式的定义是:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。适配器模式分为类结构型模式和对象结构型模式两种,前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少些。

        按照我的理解来讲,适配器就是当客户端调用的方法与实现方法的形式不一样时,我们再设计另外一个接口,对客户端给出的参数进行一定程度的处理,然后再正常调用已经实现了的方法。举个栗子,比如我们设计一个计算矩形面积的类,已经实现的方法是通过输入长和宽来计算面积。然而客户端给出的确实左上角的顶点和右下角的顶点的坐标。这时,我们可以设计一个adapter接口,通过顶点坐标计算出长和宽,再计算面积。这就是适配器模式

        优点:

            a.客户端通过适配器可以透明地调用目标接口。

            b.复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。

            c.将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。

            d.在很多业务场景中符合开闭原则。

        缺点:

            a.适配器编写过程需要结合业务场景全面考虑,可能会增加系统的复杂性。

            b.增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱。

    2.装饰器模式:

        在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。通过递归的方式对每一个特性构造子类,通过委派机制增加到对象上。这一种模式可以想象成给一个已经实现的类不断地“穿衣服”。例如,课上我们所讲的冰淇淋类的例子。我们先实现了一个原味冰淇淋的类PlainIceCream,然后我们可以构造实现IceCream接口的另一个类,也就是修饰类。在这个修饰类中增加IceCream类的参数,并添加一些诸如加糖果、坚果等功能。这样不断套娃,可以实现功能的叠加。这也是装饰器模式得名的原因。

        优点:

            a.装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用

            b.通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果

            c.装饰器模式完全遵守开闭原则

        缺点:

            a.装饰器模式会增加许多子类,过度使用会增加程序得复杂性。

    三、行为类模式:

    1.策略模式:

        有多种不同的算法来实现同一个任务,但需要client根据需要动态切换算法,而不是写死在代码里。为不同的实现算法构造抽象接口,利用delegation,运行时动态传入client倾向的算法类实例。策略模式是关于ADT内部的设计,这点要区分于visitor模式

        优点:

            a.算法可以自由切换。

            b.避免使用多重条件判断。

            c.扩展性良好。

        缺点:

            a.策略类会增多。

            b.所有策略类都需要对外暴露。

    2.迭代器模式:

        客户端希望对放入容器/集合类的一组ADT对象进行遍历访问,而无需关心容器的具体类型,也就是说,不管对象被放进哪里,都应该提供同样的遍历方式。

        优点:

            a.它支持以不同的方式遍历一个聚合对象。

            b.迭代器简化了聚合类。

            c.在同一个聚合上可以有多个遍历。

            d.在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。

        缺点:

            a.由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。

        应用场景:

            a.访问一个聚合对象的内容而无须暴露它的内部表示。

            b.需要为聚合对象提供多种遍历方式。

            c.为遍历不同的聚合结构提供一个统一的接口。

    3.访问者模式:

        在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。这种模式同样是通过委托实现的。具体实现方法如下:假设我们现在已经有一个类实现了一系列的功能,现在我们想要添加一个新方法。这时,我们可以在原类中添加一个accept(visitor)方法,并且添加visitor委托参数,然后在该方法中将自己this作为参数调用visitor中的方法。这样我们可以在visitor中设计新的功能,而不改变原有的ADT。这就是访问者模式。

        优点:

            a.符合单一职责原则

            b.优秀的扩展性

            c.灵活性

        缺点:

            a.具体元素对访问者公布细节,违反了迪米特原则

            b.具体元素变更比较困难

            c.违反了依赖倒置原则,依赖了具体类,没有依赖抽象

        应用场景:

            a.对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作

            b.需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类

  • 相关阅读:
    NSNotificationCenter 使用姿势详解
    自动监测内存泄漏
    Xcode 8:在 Active Compilation Conditions 中自定义环境变量
    iOS 10 推送必看(高阶1)
    iOS10 推送必看(基础篇)
    Xcode 8 用处不大的新特性:CLANG_WARN_INFINITE_RECURSION
    手动实现 KVO
    请谨慎使用 @weakify 和 @strongify
    UIImage图片处理,旋转、截取、平铺、缩放等操作
    Xcode代码格式化教程,可自定义样式
  • 原文地址:https://www.cnblogs.com/mzh2017/p/16372899.html
Copyright © 2020-2023  润新知