设计模式分类
创作模式
– 工厂方法模式在不指定确切类的情况下创建对象。
结构模式
– 适配器允许具有不兼容接口的类通过将自己的接口包装在现有类的接口周围来协同工作。
– 装饰器动态添加/覆盖对象方法中的行为。
行为模式
– 策略允许在运行时选择一系列算法中的一个。
– 模板方法将算法的骨架定义为抽象类,允许其子类提供具体的行为。
– 迭代器按顺序访问对象的元素,而不暴露其底层表示。
– 访问者通过将方法层次结构移动到一个对象中来将算法与对象结构分开
创建型模式中最经典的成员当属“工厂方法模式”。
该模式又被称作“虚拟构造器”,大体思想是在构建一个对象时,不去调用其具体的构造方法(比如不清楚该实例化哪个对象时),而是先创造一个接口,通过调用该接口的子类去决定实例化哪一个类。就好像我向某一个工厂提出了请求,工厂给了我产品,但是我完全不知道这个产品是如何生产出来的。在创建对象的时候,先新建一个“工厂”(工厂方法类),再调用其方法返回需要构建的类。如果工厂方法被设定成静态的,就可以不用创建新的工厂对象,直接使用ADT的静态方法即可。工厂方法模式满足了可维护性原则中的“OCP”原则(开放-封闭原则)。
结构型模式中包含了“适配器模式”与“装饰器模式”,两种模式的底层逻辑都是委托。
适配器模式的主要思路是使用接口将client和具体类方法分隔开,尽量不接触。不使用适配器时,委托对象必须是具体的某个类。而设计适配器则是首先设计适配器接口,在接口中声明需要适配的方法,接着设计一个基础适配器的抽象类去继承接口,并在基础适配器的基础上延伸出许多适应不同情况的具体适配器,每一个具体适配器去实现其对应的具体委托。能看出来实际上工厂方法也是一种针对构造方法的适配器。
“装饰器模式”则是为了应对需要实现多种功能、进行大量子类继承而导致的组合爆炸。大体思想是创建一个接口,并完成两个实现:基础类实现和基础装饰器类实现。基础装饰器类是抽象的,其构造方法需要委托基础类来实现。再根据功能需要设计出一系列继承装饰器类的具体装饰器,每一个装饰器根据需要复写基础装饰器中的某些方法。这样,在构建一个对象时,就可以像“穿衣服一样”,通过一层一层调用不同的装饰器来给为对象添加不同的功能。相较于继承,装饰器是在代码运行时实现的功能组合。
行为类模式侧重于根据ADT需要实现的不同行为进行设计,包括策略模式、模板模式、迭代器和观察器。
策略模式的大体思想是实现某个功能可能有不同的算法,那就将方法抽离出来,根据实际策略进行调用。创建策略接口,声明存在多种策略的方法,然后设计不同的子类去实现这个接口,代表不同策略的具体实现。在实际使用时,委托这些不同的策略去实现不同的方法。
模板模式则是基于继承和重写的一种设计模式,针对那些有一定顺序和模板的任务,但是每一个环节的具体实现方法可能不同,则创建一个抽象模板类,其中包含着每一个环节的抽象方法和一些通用环节的具体实现,并设定好环节顺序。之后根据需要设计其子类,完成各环节的具体实现。
迭代器模式则是让自己设计的集合类实现Iterable接口,并实现自己独特的迭代器,允许客户端使用迭代器去遍历这个集合类。
观察器的实现基于方法重载,目的是将数据与操作分离开,方便针对不同的数据进行不同的操作。设计一个观察器接口,声明对不同数据的不同操作方法,并在具体类中实现这些方法。
面向对象设计原则为支持可维护性复用而诞生,这些原则蕴含在很多设计模式中,它们是从许多设计方案中总结出的指导性原则。面向对象设计原则也是我们用于评价一个设计模式的使用效果的重要指标之一,在设计模式的学习中,大家经常会看到诸如“XXX模式符合XXX原则”、“XXX模式违反了XXX原则”这样的语句。
最常见的7种面向对象设计原则如下表所示:
单一职责原则 (Single Responsibility Principle, SRP) | 一个类只负责一个功能领域中的相应职责 |
开闭原则 (Open-Closed Principle, OCP) | 软件实体应对扩展开放,而对修改关闭 |
里氏代换原则 (Liskov Substitution Principle, LSP) | 所有引用基类对象的地方能够透明地使用其子类的对象 |
依赖倒转原则 (Dependence Inversion Principle, DIP) | 抽象不应该依赖于细节,细节应该依赖于抽象 |
接口隔离原则 (Interface Segregation Principle, ISP) | 使用多个专门的接口,而不使用单一的总接口 |
合成复用原则 (Composite Reuse Principle, CRP) | 尽量使用对象组合,而不是继承来达到复用的目的 |
迪米特法则 (Law of Demeter, LoD) | 一个软件实体应当尽可能少地与其他实体发生相互作用 |