前言
这两天逐字逐句的翻译 Java 8 数据结构的源代码有点头疼。。决定写几篇设计模式分析放松一下,哈哈。其实设计模式应该放在数据结构之前介绍,因为数据结构中也大量的使用了如适配器默认,门面模式等设计模式,了解了设计模式以后再看数据结构与其他源码会更加轻松。
什么是 OOP?
Object Oriented Programming,面向对象编程,将程序中所有的操作都抽象成与现实相近的模型,并通过相互之间的继承,实现,持有等关系,达到***封装,继承,多态***三个核心理念。
- 封装:将与某种事物有关的一系列属性和方法封装成为一个对象,使操作事物的方式更偏向于现实,将事物的内部实现隐藏起来,将方法提供出去,降低了程序之间的耦合性,提高了代码的复用性,降低了维护成本。
- 继承:继承是基于封装基础的概念,将一系列事物通用的属性与方法通过继承的方式传承下去,同样使事物之间的关系更偏向于现实,同时提高了代码的复用性,降低了维护成本。
- 多态:多态是基于继承基础的概念,对于有继承关系的事物,使用传承的属性与方法时,在程序运行前不确定最终由哪个事物来最终实现,在程序运行期间才确定。提高了程序的复用性,降低了维护成本。
什么是设计模式?
设计模式是基于 OOP 的三个核心理念衍生出的,为了更好,更趋向于现实,更高的复用代码的,由前人不断在实践中归纳总结出的一系列设计程序的模式。
设计模式遵循什么样的原则?
并不是任何一种模式都可以成为经典的设计模式的,一般设计模式主要遵循七大原则:
(1)开闭原则(Open Close Principle)
描述:对扩展开放,对修改关闭
释义:在真实的编写程序的过程中,程序是一个逐渐完成的过程,不能保证某个已经定义的事物在未来不会发生改变,但是这个时候事物可能已经存在很长时间了,对于它的任何修改可能导致不可预料的问题,这个时候就要选择扩展而非修改的方式,扩展事物对于新改变的实现,保持原来的程序不变。
(2)单一职责原则
描述:每个类应该实现单一职责
释义:试想一种情况,如果多个事物都实现了相同的职责,这里的相同指的是在功能上的完全相同,那么势必有一个是多余的,而在选择实现的时候会不知道应该选择哪一种。如果多个事物都需要完成相同的职责,那么这种职责的实现应该放在它们的父类事物中。
(3)里氏替换原则
描述:任何基类出现的地方,子类一定可以出现
释义:基于 继承 的概念,子类事物一定包含了父类食物中的所有属性与方法,所以在程序中任何父类事物的行为,替换成子类事物一定也是可以实现的。
(4)依赖倒转原则
描述:面向接口编程,依赖于抽象而不依赖于具体
释义:这个与 里氏替换原则 类似,这不过这里的父类事物换成了接口,用于接口的实现类事物一定实现了接口中的方法,所以在程序中任何接口的行为,替换成实现类事物一定也是可以的。而接口的出现是为了定义某种能力,面向接口编程即是面向能力编程,只对外声明我使用了这种能力,能力的具体实现由实现类事物来决定。
(5)接口隔离原则
描述:接口不存在子类用不到却必须实现的方法,否则就要拆分接口
释义:由于接口中不存在方法的具体实现,必须有实现类事物自行实现,所以一旦定义了实现类用不到的方法,实现类将不得不实现这些方法,而这些方法显然是多余的,通过拆分接口,拆分能力,可以解决这个问题。不要以为 Java 8 提供了接口默认实现之后,这一条就不适用了,接口默认实现的那些方法必须是实现类事物必须的,这种新特性只是为实现类事物提供了一种更精简的编程方式
(6)迪米特法则
描述:一个类对自己依赖的类知道的越少越好
释义:最高级的封装方式是,完全隐藏内部实现,一个事物对于其他事物的实现方式了解的越少越好。这样可以降低不同事物之间的耦合,降低程序的维护成本。
(7)合成复用原则
描述:首先使用合成/聚合的方法,而不是使用继承
释义:这一点有点像 单一职责原则 与 迪米特法则 的结合,如果在现实中一个事物并不属于另一个事物,它应该通过合成/聚合的方式来操作事物,因为继承关系对它来说是不切当的。同时通过合成/聚合的方式操作另一个事物是不必知道另一个事物的实现细节的,使用合成/聚合的方式能避免不必要的继承关系,使得事物之间的关系更加合理。
主要有哪些经典设计模式?
根据 Wikipedia 的简介,总共存在 4 种类型的设计模式,Wiki 的介绍也非常简单。
创建型模式
在软件工程中,创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。
创建型模式由两个主导思想构成。一是将系统使用的具体类封装起来,二是隐藏这些具体类的实例创建和结合的方式。
创建型模式又分为对象创建型模式和类创建型模式。对象创建型模式处理对象的创建,类创建型模式处理类的创建。详细地说,对象创建型模式把对象创建的一部分推迟到另一个对象中,而类创建型模式将它对象的创建推迟到子类中。 摘自 Wiki
模式名称 | 描述 |
---|---|
抽象工厂模式 | 为一个产品族提供了统一的创建接口。当需要这个产品族的某一系列的时候,可以从抽象工厂中选出相应的系列创建一个具体的工厂类。 |
工厂方法模式 | 定义一个接口用于创建对象,但是让子类决定初始化哪个类。工厂方法把一个类的初始化下放到子类。 |
生成器模式 | 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 |
惰性初始模式 | 推迟对象的创建、数据的计算等需要耗费较多资源的操作,只有在第一次访问的时候才执行。 |
对象池模式 | 通过回收利用对象避免获取和释放资源所需的昂贵成本。 |
原型模式 | 用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。 |
单例模式 | 确保一个类只有一个实例,并提供对该实例的全局访问。 |
多例模式 | 确保一个类只有命名的实例,并提供对这些实例的全局访问。 |
资源获取为初始化 | 通过绑定到合适对象的生命周期来确保资源被适当地释放。 |
Dependency Injection | A class accepts the objects it requires from an injector instead of creating the objects directly. |
Multiton | Ensure a class has only named instances, and provide a global point of access to them. |
结构型模式
在软件工程中结构型模式是设计模式,借由一以贯之的方式来了解元件间的关系,以简化设计。摘自 Wiki
模式名称 | 描述 |
---|---|
适配器模式 | 将某个类的接口转换成客户端期望的另一个接口表示。适配器模式可以消除由于接口不匹配所造成的类兼容性问题。 |
桥接模式 | 将一个抽象与实现解耦,以便两者可以独立的变化。 |
组合模式 | 把多个对象组成树状结构来表示局部与整体,这样用户可以一样的对待单个对象和对象的组合。 |
修饰模式 | 向某个对象动态地添加更多的功能。修饰模式是除类继承外另一种扩展功能的方法。 |
外观模式 | 为子系统中的一组接口提供一个一致的界面, 外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 |
享元 | 通过共享以便有效的支持大量小颗粒对象。 |
代理 | 为其他对象提供一个代理以控制对这个对象的访问。 |
Extension object | Adding functionality to a hierarchy without changing the hierarchy. |
Front controller | The pattern relates to the design of Web applications. It provides a centralized entry point for handling requests. |
Marker | Empty interface to associate metadata with a class. |
Module | Group several related elements, such as classes, singletons, methods, globally used, into a single conceptual entity. |
Twin | Twin allows modeling of multiple inheritance in programming languages that do not support this feature. |
行为型模式
在软件工程中, 行为型模式为设计模式的一种类型,用来识别对象之间的常用交流模式并加以实现。如此,可在进行这些交流活动时增强弹性。摘自 Wiki
模式名称 | 描述 |
---|---|
黑板 | 广义的观察者在系统范围内交流信息,允许多位读者和写者。 |
责任链 | 为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。 |
命令 | 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。 |
解释器 | 给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。 |
迭代器 | 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。 |
中介者 | 包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用,从而使它们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化。 |
备忘录 | 备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。 |
空对象 | 通过提供默认对象来避免空引用。 |
观察者模式 | 在对象间定义一个一对多的联系性,由此当一个对象改变了状态,所有其他相关的对象会被通知并且自动刷新。 |
规格 | 以布尔形式表示的可重绑定的商业逻辑。 |
状态 | 让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能获取的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。 |
策略 | 定义一个算法的系列,将其各个分装,并且使他们有交互性。策略模式使得算法在用户使用的时候能独立的改变。 |
模版方法 | 模板方法模式准备一个抽象类,将部分逻辑以具体方法及具体构造子类的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先构建一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。 |
访问者 | 封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改,接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。 |
Servant | Define common functionality for a group of classes. The servant pattern is also frequently called helper class or utility class implementation for a given set of classes. The helper classes generally have no objects hence they have all static methods that act upon different kinds of class objects. |
并发型模式
在软件工程中,并发型模式是用来处理多线程编程范式的一类设计模式。摘自 Wiki
模式名称 | 描述 |
---|---|
主动对象 | Decouples method execution from method invocation that reside in their own thread of control. The goal is to introduce concurrency, by using asynchronous method invocation and a scheduler for handling requests. |
阻碍 | 未找到定义 |
双重检查锁定 | Reduce the overhead of acquiring a lock by first testing the locking criterion (the ‘lock hint’) in an unsafe manner; only if that succeeds does the actual locking logic proceed. Can be unsafe when implemented in some language/hardware combinations. It can therefore sometimes be considered an anti-pattern. |
守卫 | Manages operations that require both a lock to be acquired and a precondition to be satisfied before the operation can be executed. |
领导者/追随者 | 未来找到定义 |
检测对象模式 | An object whose methods are subject to mutual exclusion, thus preventing multiple objects from erroneously trying to use it at the same time. |
读写锁 | Allows concurrent read access to an object, but requires exclusive access for write operations. |
调度 | Explicitly control when threads may execute single-threaded code. |
线程池模式 | A number of threads are created to perform a number of tasks, which are usually organized in a queue. Typically, there are many more tasks than threads. Can be considered a special case of the object pool pattern. |
线程特定存储 | Static or “global” memory local to a thread. |
反应器 | A reactor object provides an asynchronous interface to resources that must be handled synchronously. |
Balking | Only execute an action on an object when the object is in a particular state. |
Binding properties | Combining multiple observers to force properties in different objects to be synchronized or coordinated in some way. |
Compute kernel | The same calculation many times in parallel, differing by integer parameters used with non-branching pointer math into shared arrays, such as GPU-optimized Matrix multiplication or Convolutional neural network. |
Event-based asynchronous | Addresses problems with the asynchronous pattern that occur in multithreaded programs. |
Join | Join-pattern provides a way to write concurrent, parallel and distributed programs by message passing. Compared to the use of threads and locks, this is a high-level programming model. |
Lock | One thread puts a “lock” on a resource, preventing other threads from accessing or modifying it. |
Messaging design pattern (MDP) | Allows the interchange of information (i.e. messages) between components and applications. |
其中斜体加粗标示的一些设计模式是比较常用的一些。下一篇将介绍与分析创建型模式的中的一些设计模式。