- 项目更好维护
- 实现更优雅
- 读源码更轻松
- 理解面向对象
设计模式是解决很多问题的更优雅的实现,很多项目难以维护或者难以拓展都是因为设计的时候很多没有做好。
当然这里一开始只有最简单的 GoF23种设计模式,后面会考虑将Spring或者其他源码里面抽出,结合设计模式来讲,可能会更好一些
很多优秀的开源组件框架都大量用到设计模式,很多时候你看不懂,或者读起来也就那样,没有那种原来如此,令你眼前一亮的感觉。其实就是设计模式你还没有理解。比如我一开始看Spring的Ioc实现原理,我根本没有看出来他哪里优秀了。怎么就来了个革命性的成果呢(我当时没有读设计模式,代码写的也少)
现在看,跟以前看是不一样的,不过仍然还是没有抓住他的要点。毕竟设计模式的思想真的他高深了
- 《图解设计模式》的所有代码实现,部分后面习题代码(代码中也会有注释和笔记)
- 图解设计模式的笔记
- 记录我学设计模式的时候的感想、经验。比如总结一下生成实例的三种方法,哪些用了单例,委托、Tamplate
- 各个设计模式的优缺点、场景
- 抽象类中的方法可以是具体类,也可以是抽象类(具体可以看Tamplate模式的使用)。接口全部是抽象类,且公共
- 抽象类需要继承,接口需要实现。这两个的区别主要在 父类多的情况下,Java继承只能单继承,但可以实现多个接口。(比如我们在Adapter模式的时候,他有两种实现方式,一种继承,一种委托。一个使用接口,一个使用抽象类)
- 欢迎补充,暂时想到这么多。之前想到了没有记下来,忘完了
- 声明和实现分离,便于直观了解
- 弱化各个程序间的耦合,实现可复用
- 各个处理流程在抽象类阶段确立
- 如果传入的是他们两个的父类,调用者并不需要知道具体的是哪一个子类,(参考Composite模式,其实基本上大部分都会体现,如第一个Iterator模式,在我们BookShelf调用BookShelfIterator的时候,用于返回的是Iterator,而不是BookShelfIterator。不过Composite模式更直观)
在我第一个节点,为啥要看设计模式的时候有一个理由写道,理解面向对象。很多人可能会不太服,我学了面向对象语言(如Java)那么久,早就已经掌握了面向对象的思想。从开始学Java的时候,就天天提到面向对象的三大特性,封装、继承、多态。傻子都背熟了,面向对象也没啥难的。
真的是这样吗?我们说到Java是一个面向对象的语言,皆可对象,所有的都可以当作对象来处理,就连8个基本类型,都有他们的装箱类。我们只要将东西抽象成对象就行了。是这样吗?
如果你只是按照上面的来想,那真的就太太太小看面向对象了。
如果按照上面的逻辑理解面向对象,那么C语言也可以称为面向对象的语言了。因为他可以定义 Struct,结构体,和Java这种面向对象语言的样子很类似。所以这个并不能使一个语言成为面向对象的语言
关键还是忽略了,面向对象的强大的后面两个——继承、多态。我入职第一周,写程序。写出来是面向过程的,老大让我把程序改成面向对象的。然后我就定义了几个类,将变量值改成对象的属性。(想想还是憨)
我们老大说,你这不还是面向过程吗?面向对象体现在哪里? 连个继承和多态都没有。
后来我定义了个抽象父类,勉勉强强算是打成了改成面向对象的目标。
所以,仅仅只有类和对象,是不能被称为面向对象的
继承是多态的前提条件。只有有了继承,并且重写了父类的方法,才会有多态
但是我们一写到程序里,往往就不会想着使用这两个。因为面向过程更符合我们的思考方式,想到啥逻辑,一气呵成就写完了
但是那样不好维护,这种只有等你真正实战才能体会,光纸上谈兵是根本体会不了的
多态的实质是Java的动态分派,如果有兴趣,可以看下我的JVM中的这篇文章。重写和重载的区别
抽象这个概念很不好理解,因为他本来就很抽象
我们把现实中的物体的某些事物的共同特征找出来,然后总结一下,这就是抽象的过程。
比如我们本子,盒子,书这些生活中具体的事物,我们找到他的共同特征,都有12个点,8条棱,6个面。并且相对的棱都是平行的,相对的面也是平行的。然后我们就抽象出了一个图形——长方体。长方体就是我们抽象出来的东西。我们不讲究他的颜色、材质、重量等等。
这个过程就像我们创建类一样,找到公共的属性,然后进行抽象,变成一个类。
这是抽象的第一步,创建具体类
我们在抽象的基础上再进行抽象。抽象的东西还能再抽象吗?当然可以
再往上抽象就变成了 抽象类,抽象类因为比类还抽象,所以他不能直接实例化,但是可以被其他具体子类继承
这个抽象类里面,有两种方法
- 抽象方法,只声明,但是不实现。
- 普通方法,普通类中的方法一样,需要具体实现
但是这两个方法都可以被子类重写,从而实现 多态
我们还可以再抽象。我们属性都不要。就只要方法(函数、行为),并且这些方法都必须是抽象方法
这就是第三步的抽象,接口
还能再抽象?类方面我们不能再抽象了,不过我们能把这些组合抽象一下。
于是,设计模式就诞生了。著名的设计模式,是GoF总结的23种。当然,不止GoF这一种,也不是他们发明创造的,他们只是将大家做的总结出来了而已。而且23种设计模式还只是基础。
我们实际工作中可能还要用到多种设计模式组合出的东西
所以如果学习设计模式,你不了解 抽象类和接口的妙用,是根本就没有懂设计模式
如果不懂基础的23种设计模式,那你可能连面向对象的门都没入
关于抽象类还有接口,我现在说,不懂的还是不懂,我只能在各个设计模式中给大家讲我的分享
我只能分享一下我的学习方法,不一定是最优的,但可以作为参考
首先拿到这本书我是懵的,因为这个东西太抽象了。学编程都知道,很多东西都是抽象抽象再抽象。而设计模式更是将之前的面向对象又往上抽象了一下。所以新手一开始不懂非常正常,我看了两三遍才勉强看懂为啥这样做
- 你可能看不懂代码为啥这样写,也没必要一定要搞懂为啥这个设计模式要这样。但是一定要把代码敲一遍
- 看清楚哪些用了接口,哪些用了抽象类
- 然后看12个设计模式,先看一半。
- 你已经看了一半,基本已经有一些想法了。知道接口和抽象类的不同和好处
- 然后回头重新看,并且再把代码跟着敲一遍,这个时候要想一下,他们是怎么调用的,有啥好处
- 再想一下哪里用到了相似的,并且再看到一半
- 已经看了两遍,代码也敲了两遍。基本每个模式的例子都有印象了
- 跟着他的 UML 图试着还原他的设计模式
- 找出那些设计模式很相似,或者这个设计模式嵌套了另一个设计模式(比如Tamplate模式被非常多的模式都用了,有哪些,为啥这样做)
- 找到相关的源码,比如 线程池用到了 工厂模式。看他怎么使用的工厂模式
- 最好结合实际来。比如我之前就被老大叫去使用单例写一个小工具。之前改程序的时候也用到Tamplate模式
这样子下来,基本算是稍微掌握了设计模式,更多的就需要自己在项目中刻意练习了
- Iterator
- 好处:将遍历和实现分离,即while循环中的东西不依赖于BookShelf的实现
- Adapter
- 目的:让新的接口对原来的方法能够在不改的前提下对之前的进行兼容
- 使用 继承和委托的区别
- 委托需要注入,然后再调用
- Template
- 这个模式挺重要的,后面很多模式会大量用到
- 父类定义整个处理流程,子类实现具体步骤
- Factory
- 不用自己手动来new实例,而是通过工厂来创建实例,实现和类名之间的耦合
- 工厂模式很多地方用到了,比如线程池。
- Singleton
- 这个是面试问的最多的,很多人熟悉,但是很多人不明白各种单例
- 懒汉,饿汉,双重校验锁。这些你都会吗? 双重校验锁再加volatile关键字呢?
- Singleton 这个模式很重要,以后工作也会大量用到。面试更不用说
- Prototype
- 根据现有的实例 来生成新的实例
- 除了使用 new 和 使用 反射的 newInstance 我们还有使用 clone的方法生成实例
- 因为返回的是MessageBox和UnderlinePen 是Product的实现,所以在create方法的返回可以使用 Product来接收这两个方法的createClone方法的返回值
- Builder
- 和Tamplate类似,但是Builder的子类调用顺序在Director中,Tamplate在父类中
- Builder 感觉就是 委托+Tamplate
- Abstract Factory
- 优缺点:
- 优点:易于增加具体工厂
- 缺点:难以增加新的零件(因为已经全部写死在抽象父类,要改之前所有的具体工厂都要改)
- 在Item中,他的子类 Link 和 Tray 都是他的子类,所以在Page和Tray增加的时候中直接传入Item就行了,不需要知道具体是Link还是Tray
- 优缺点:
- Bridge
- 类的层次结构的两个作用
- 增加新的功能
- 增加新的实现
- Bridge 使用 委托+Tamplate
- 将类的功能层次和类的实现层次连接起来
- 类的层次结构的两个作用
- Strategy
- 将整个算法替换,能替换的基础还是都实现自Strategy接口。而且二者所有的都相同,只是函数实现方式不同
- 这里面的例子也有使用Singleton模式
- 也是用了委托
- Composite
- 能够使容器和内容具有一致性
- 不必知道传过来的是谁,只要知道他的父类就行
- Decorator
- 装饰边框与被装饰物具有一致性
- Singleton,不用说
- Factory
- Adapter 委托基本后面都要用到
- Proxy
- Tamplate 基础,后面很多模式都会用到这个模式
- Chain Of Responsibility
- Observer
- Mediator
- Flyeight
- Factory
- Abstract Factory
- Bridge
- Decorator
- Adapter
- Bridge
- Strategy
- Decorator
- new 关键字(这个用的最多)
- Class.forname().newInstance().这个也常见
- clone 这个不常见,但是也很有用在prototype中