目录
一、主要内容
1.三大类及两小类
三大类(创建型、结构型、行为型)
创建型模式(五种):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
结构型模式(七种):适配器模式、代理模式、装饰器模式、组合模式、外观模式、桥接模式、享元模式
行为型模式(十一种):观察者模式、策略模式、命令模式、模板方法模式、迭代子模式、责任链模式、备忘录模式、状态模式、访问者模式、中介模式、解释器模式
两小类
并发型模式、线程池模式
2.六大原则
1)单一原则:一个类只负责一项职责
2)开闭原则:对扩展开放,对修改关闭(不修改原有代码实现热插拔,利用接口与抽象类实现)
3)里氏替换原则(开闭原则扩展):子类型能够替代父类型,使得程序行为不发生变化
4)依赖倒转原则(开闭原则基础):针对接口编程,依赖抽象不依赖具体;即,高层模块不依赖于低层模块,两者都应该依赖抽象,同时应该是细节依赖抽象而非抽象依赖细节
5)接口隔离原则:程序不应依赖它不需要的接口,一个类对另一个类的依赖应该建立在最小的接口上
6)迪米特法则(LKP:Least Knowledge Principle,最少知识原则):一个类只要知道另一个类中它需要调用的方法,其他应尽量少知道(朋友关系越密切耦合度越高)
注:合成复用原则(LKP的衍生):尽量使用合成/聚合,不要使用类继承
聚合:代表整体的对象包含代表部分的对象(班级包含学生,培训班包含学生),整体不在,部分依然存在
合成:合成的整体对象对其组成部分拥有完全的支配权、生命周期一致,整体over部分也不在了
二、创建型
1)工厂方法模式
简单工厂:一个工厂类,对实现同一接口的类进行实例创建
多个工厂方法:一个工厂类,对实现统一接口的类都有一个实例创建方法
静态工厂:多个工厂方法设为静态的直接调用,不需要创建工厂类实例
2)抽象工厂模式
提供工厂接口,对实现同一个接口的多个类,在生产实例时建个对应类的类工厂生产该类;比如现有猫厂实现工厂接口,调用生产方法生成实现了动物接口的一只猫。
3)单例模式
标准单例:使用静态方法获取实例,方法内部若是对象为空则生成,不为空直接返回对象
方法同步的单例:在标准单例的获取方法上加synchronized关键字同步
以上两种不推荐,并发也会出问题,以下是基于并发的解决方案:
双重检查锁定单例:在静态获取实例的方法中两次判断实例是否为空(两个判断嵌套),在第一个判断为空时进入方法块加synchronized锁定第二次判断是否为空的语句块
(上述同步时可能出现new对象后进行赋值时还没有初始化,引用被外部对象调用,即:a=new X()时a被外部引用,可是类(分配空间->初始化->引用)在多线程环境会可能直接在未完成初始化时引用,导致出错)
括号内的解决方案有以下两种:
volatile静态变量双重检测单例:在双重检测的基础上,声明静态对象变量的时候使用volatile声明,保证多个线程之间的可见性(通过禁止初始化->设置引用的重排序实现)
静态内部类单例(类初始化解决方案):使用一个静态内部类直接在声明静态对象的时候new一个新对象(利用静态变量只初始化一次的特性),在静态获取方法中直接返回静态内部类的静态对象
4)建造者模式
一个建造接口负责一个整体对象创建的各个方法,不同的建造者实现不同的对象生产,一个指导者使用不同建造者作为参数传入构造函数初始化生成,负责按不同顺序调用建造者的方法
5)原型模式
将一个对象作为原型,对其进行复制、克隆产生一个和原对象类似的新对象(java中类的clone方法通过继承cloneable接口(空接口,所以可以将clone命名为任意名称),主要是在clone中要调用super.clone方法将会自动调用object的clone方法,这是一个native方法)
浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。
深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底。
三、结构型
6)适配器模式
适配中间件,用于连接不匹配的二者,将不匹配变得匹配,有三种:
类适配器:接口A的方法A,接口B的方法B,现需要对A访问,方法却存在B中,适配器类Adapte通过继承B的接口实现类并实现接口A,这样就可以在Adapter中不改变访问A的情况下访问B的方法(在A方法中调用B方法)
对象适配器模式:在类适配器的场景上,适配器类Adapter继承要访问的A接口,将B的实现类声明为私有变量,直接在继承于A的实现方法中调用B实现类的实例方法
接口适配器:接口A有一堆的方法,抽象类Adapter通过实现A接口的所有方法为空方法,在需要使用时,直接实现Adapter中的某个方法即可
7)装饰器模式
动态的给一个对象增加一些新的功能,装饰与被装饰者实现同一接口,在装饰者中声明接口(构造器传入被装饰者为参数),在装饰方法内部调用被装饰者的方法(比如在调用被装饰者的方法前的方法可以实现为一个装饰器,在调用后也可以实现为一个装饰器,装饰器是指的一个团队的装饰器,不止一个)
8)代理模式
(与基本的装饰模式很像,感觉就像拥有前后环绕方法的装饰器模式)
静态代理:目标对象与代理对象实现同一接口,在代理对象中用接口的静态声明,用构造器注入目标对象,在接口方法中调用目标对象的方法实现功能增强
动态代理: 目标对象实现一个接口,使用JDK中的类Proxy的newProxyInstance(目标对象的类加载器,目标类实现的接口类型数组,事件处理接口) 方法进行动态生成
Cglib代理:目标对象不需要实现接口,直接在代理工厂类中(引入Cglib的jar包)继承MethodInterceptor类,编写一个获取代理对象的方法和重写intercept方法
代理模式与装饰器模式区别:
代理模式(Proxy 模式)可理解为:我想做,但不能做,我需要有一个能干的人来帮我做。
装饰器模式(Decorator 模式)可理解为:我想做,但不能做,我需要有各类特长的人来帮我做,但我有时只需要一个人,有时又需要很多人。
9)组合模式
组合模式,就是在一个对象中包含其他对象,这些被包含的对象可能是终点对象(不再包含别的对象),也有可能是非终点对象(其内部还包含其他对象,或叫组对象),我们将对象称为节点,即一个根节点包含许多子节点,这些子节点有的不再包含子节点,而有的仍然包含子节点,以此类推。(例:一个抽象类,终点对象和非终点对象均继承自抽象类;或文件结构的目录与文件)
10)外观模式
一个外观角色类包含各个子系统角色类的声明,在外观角色类的方法中逐一调用多个子系统角色类的方法,还有一个客户角色通过调用外观类的方法完成要实现的功能
11)桥接模式
由四个角色:抽象化角色(抽象类,持有一个实现化角色接口的引用,给出基于底层更高一层的操作),修正抽象化角色(继承扩展抽象化角色的类),实现化角色(接口/抽象类,方法不一定要和抽象接口相同,只给出底层操作),具体实现化角色(实现化角色接口具体实现)
一个修正类继承一个持有实现化角色的抽象类,具体实现化类有很多,在修正类的方法中调用相关方法
12)享元模式
享元模式以共享的方式高效地支持大量的细粒度对象。 也就是说在一个系统中如果有多个相同的对象,那么只共享一份就可以了,不必每个都去实例化一个对象。
享元对象能做到共享的关键是区分内蕴状态(Internal State)和外蕴状态(ExternalState)。
内蕴状态:存储在享元对象内部的,并且是不会随环境的改变而有所不同。因此,一个享元可以具有内蕴状态并可以共享。
外蕴状态:随环境的改变而改变的、不可以共享的。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。外蕴状态不可以影响享元对象的内蕴状态,它们是相互独立的。
单纯享元模式:一个享元接口定义方法,一个具体享元角色负责实现方法及为内蕴状态提供存储空间,一个享元工厂负责创建管理享元对象(即所有享元对象都通过享元工厂创建,一个内蕴状态为黑色的五子棋显示的外蕴状态为序号5,表示一个享元对象,单纯享元认为所有的享元对象是可共享的)
复合享元模式:复合享元对象本身不可共享,可通过分解成多个单纯享元对象,来共享单纯享元对象。
四、行为型
11种模式的关系:
第一类:通过父类与子类的关系进行实现。第二类:两个类之间。第三类:类的状态。第四类:通过中间类
13)观察者模式
一个观察者接口,一个主题接口,两者都有许多具体实现类,具体主题类持有一个观察者列表(内存多个具体观察者),等具体主题类有消息要通知时遍历观察者列表来调用方法
14)策略模式
一个抽象策略角色(Comparator接口),一个具体策略角色(对Comparator实现,包装具体的算法和行为),一个环境角色类(TreeSet):TreeSet的Comparator的排序
15)命令模式
一个调用者(发布命令的人)持有一个命令接口的声明变量,在其方法中调用命令的执行方法;一个命令的具体实现者持有一个命令执行者(接收命令,接收者)的声明,在命令对象的方法中调用接收者的方法;这样调用命名的人通过发出(调用)命令,让接收者去执行
16)模板方法模式
一个抽象类定义许多方法,一个具体类对抽象类的某个方法重写,即一个计算抽象类,有加法、减法等具体类对计算方法重写
17)迭代子模式
一个抽象迭代子角色(Iterator)定义遍历元素需要的接口,一个具体迭代子角色实现Iterator接口并保持迭代过程中游标位置(访问的位置),一个聚集角色给出创建迭代对象的方法接口,一个具体聚集角色实现具体的创建迭代对象的方法返回一个迭代对象,客户端通过新建聚集对象调用迭代方法获得迭代器遍历聚集对象中的所有元素
18)责任链模式
(过滤器)每个对象持有下一个对象的引用形成的一条链
一个链对象维护一个规则对象列表及当前访问索引并且在在调用链传入自己(链对象)然后获取当前索引的规则对象(直到索引超出范围返回)执行规则方法,一个规则接口定义规则方法参数必有一个链对象的声明,规则对象实现具体方法,在方法中调用传入的链对象的规则方法,形成一个完整的链,链的开头由链对象规则方法进入由index索引判断是否超出维护的规则对象大小而退出
举例:过滤器的实现,过滤链维持多个过滤器,每个过滤器有一个doFilter方法需要使用chain.doFilter方法
19)备忘录模式
一个原始对象(设置一个恢复方法接收备份对象为参数),一个备份对象(备份原始对象的属性值),一个备忘录对象(存储备份对象)
20)状态模式
单个状态类:一个状态类(State)内部持有一个状态属性并定义了许多方法,一个状态管理类(Context)持有一个状态对象并定义方法负责判断不同状态的调用方法
多个状态类:一个状态接口定义方法,多个状态类实现状态接口返回状态对象,一个状态管理器定义方法负责调用接口的方法
21)访问者模式
根据对象的类型而对方法进行的选择,就是分派(Dispatch),分派(Dispatch)又分为两种,即静态分派和动态分派。
静态分派(Static Dispatch)发生在编译时期,分派根据静态类型信息发生。静态分派对于我们来说并不陌生,方法重载就是静态分派。
动态分派(Dynamic Dispatch)发生在运行时期,动态分派动态地置换掉某个方法。
访问者模式:一个抽象访问者接口定义不同节点类(被访问者)的同名方法、例:visit(重载),一个具体访问者实现visit方法调用不同节点类型参数的节点方法,一个抽象节点定义访问者对象为参数的接受操作(accept),一个具体节点实现访问者对象的visit方法的调用并定义了其他该节点特有的方法,一个结构对象维护一个节点列表与一个参数为访问者的执行方法。
通过结构对象的执行方法传入访问者对象,结构对象维护的节点列表的节点类执行接受accept(访问者)的操作,由于accept的方法实现中访问者调用了自身的访问方法、即访问者传递节点对象根据节点对象的类型不同执行具体的方法。
22)中介模式
用一个中介对象持有其他需要相互引用的同事对象,避免产生混乱的相互依赖的结构
一个抽象中介者定义相互引用的同事对象需要的方法contact,一个具体的中介者持有所有具体同事对象的声明及contact方法的实现(协调各同事对象实现协作行为),一个抽象同事角色持有中介对象用构造器参数传入,多个具体同事类实现自己的方法并实现通信方法contact、在其中调用中介者的通信方法。
简言之,同事对象通信时通过通信方法,通信方法调用持有的具体中介者类的通信方法,根据同事的类型使用不同的方法
23)解释器模式
一个抽象表达式角色声明所有表达式都要的一个接口interpret(解释操作),一个终结符角色(表达式基本元素,如数字1),一个非终结符(表达式操作符, 如运算符+),一个环境角色包含全局信息
简言之,除定义的环境角色Context不继承表达式Expression外,其余的终结与非终结对象均实现解释方法,环境角色存所有表达式对象的值,在表达式对象调用解释方法的时候返回。
五、并发型模式、线程池模式
任务和主动对象(Active Object):并发编程模式:
https://blog.csdn.net/wojiuguowei/article/details/78112573
线程池模式:
事先启动一定数目的工作线程。当没有请求工作的时候,所有的工人线程都会等待新的请求过来,一旦有工作到达,就马上从线程池中唤醒某个线程来执行任务,执行完毕后继续在线程池中等待任务池的工作请求的到达。
参与角色:
1)Client参与者,发送Request的参与者
2)Channel参与者,负责缓存Request的请求,初始化启动线程,分配工作线程
3)Worker参与者,具体执行Request的工作线程
4)Request参与者
六、参考文章
[1] java设计模式:https://blog.csdn.net/zane3/article/details/70304545
[2] 大话设计模式(读后感)——23种设计模式、六大原则:
https://www.cnblogs.com/jesonjason/p/5402627.html
[3] 简单粗暴,Java设计模式六大原则的理解:
https://www.jianshu.com/p/068b2d0ce4e6
[4] 聊聊设计模式原则(二) -- 接口隔离原则:
https://www.jianshu.com/p/76427d048491
[5] Java设计模式——合成/聚合复用原则:
https://blog.csdn.net/u010832572/article/details/45007933
[6] 设计模式(十六):建造者模式:
https://www.cnblogs.com/jenkinschan/p/6426694.html
[7] Java设计模式之《适配器模式》及应用场景:
https://www.cnblogs.com/V1haoge/p/6479118.html
[8] 代理模式和装饰器模式区别:
https://blog.csdn.net/andong154564667/article/details/80258061
[9] 理解java的三种代理模式:
https://www.cnblogs.com/boboxing/p/8126046.html
[10] java设计模式之外观模式:
https://www.cnblogs.com/lfxiao/p/6816900.html
[11] java设计模式之外观模式(门面模式):
https://www.cnblogs.com/lthIU/p/5860607.html
[12] Java设计模式之《组合模式》及应用场景:
https://www.cnblogs.com/V1haoge/p/6489827.html
[13] JAVA 设计模式 组合模式:
https://www.cnblogs.com/jingmoxukong/p/4221087.html
[14] 《JAVA设计模式》之桥接模式(Bridge):
https://www.cnblogs.com/betterboyz/p/9361784.html
[15] java设计模式之享元模式:
https://blog.csdn.net/u014082714/article/details/78693677
https://blog.csdn.net/lemon_tree12138/article/details/51241598
[16] Java设计模式之策略模式详解:
http://baijiahao.baidu.com/s?id=1601547440739500969&wfr=spider&for=pc
[17] 观察者模式和事件委托:
https://www.jianshu.com/p/d8f543575a43
[18] JAVA设计模式之观察者模式:
https://www.cnblogs.com/luohanguo/p/7825656.html
[19] 《JAVA与模式》之迭代子模式:
https://www.cnblogs.com/java-my-life/archive/2012/05/22/2511506.html
[20] Java设计模式系列之责任链模式:
https://www.cnblogs.com/ysw-go/p/5432921.html
[21] Java设计模式之状态模式:
https://www.cnblogs.com/love540376/p/6781577.html
[22] 《JAVA与模式》之访问者模式:
https://www.cnblogs.com/java-my-life/archive/2012/06/14/2545381.html
[23] Java设计模式系列之中介者模式:
https://www.cnblogs.com/ysw-go/p/5413958.html
[24] 《JAVA与模式》之解释器模式
https://www.cnblogs.com/java-my-life/archive/2012/06/19/2552617.html
[25] 任务和主动对象(Active Object):并发编程模式:
https://blog.csdn.net/wojiuguowei/article/details/78112573
[26] Java多线程设计模式之线程池模式: