https://www.bilibili.com/video/BV1RC4y1H7ok/?p=2
https://gitee.com/lixl/web-demo.git
23种设计模式
创建型
- singleton
- factory method
- abstract factory
- builder
- prototype
结构型
- adapter
- bridge
- composite
- decorater
- facade
- flyweight
- proxy
行为型
- chain of responsibility
- command
- interpreter
- iterator
- mediator
- memento
- observer
- state
- strategy
- template method
- visitor
单例模式singleton
静态方法单例
1 | package com.p1; |
静态内部类单例
1 | package com.demo.p1; |
DCL单例
1 | package com.p1; |
枚举单例
1 | package com.p1; |
spring-bean单例
Spring创建Bean的scope(prototype/singleton)默认为singletonorg.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
策略模式strategy
- java.util.Comparator接口
java.util.Arrays.sort(T[] a, Comparator<? super T> c)
java.util.Collections.sort(List<T> list, Comparator<? super T> c)
实现两种策略(通过年龄和重量两种属性排序),通过sort方法调用后给数组排序
classDiagram class java_util_Arrays java_util_Arrays: +sort(T[] t, Comparator c) class Comparator <> Comparator Comparator: +compare(Object o1, Object o2) int java_util_Arrays o-- Comparator class AnimalAgeComparator AnimalAgeComparator: +compare(Object o1, Object o2) int class AnimalWeightComparator AnimalWeightComparator: +compare(Object o1, Object o2) int AnimalAgeComparator ..|> Comparator : impl AnimalWeightComparator ..|> Comparator : impl class Main Main: +execute() Main ..> java_util_Arrays : invoke
工厂模式factory
1.能生成对象的类或者方法,都是工厂
2.单例也是一种工厂模式
3.比直接用new创建对象好,可以控制对象的生成过程
简单工厂
与策略模式类似,工厂生产不同的种类的产品,方便控制不同产品生产过程静态工厂
工厂方法
抽象工厂
不直接生产产品,而是调用抽象工厂生产抽象的产品(好像是对不同类型但有些相同点的产品都用抽象工厂来生产)spring IOC
spring-BeanFatory
门面模式/调停者模式
如消息中间件,可以给各个组件解耦
装饰器模式
1.增强某个类的功能,与代理模式相同
观察者模式 observer
1.Observer、Listener、Hook、Callback、js event 都是观察者模式
2.以事件监听器为例理解
SourceEvent 事件源对象,由事件产生
EventListener 事件监听者(可以有多个),接收事件源并处理
EventObserver 事件观察者,把事件源对象传递给监听者
组合模式 composite
封装树形结构的节点
如文件:File(file/directory)
享元模式 flywight
1.共享元对象,不重新创建多个小对象了
2.池化思想,如数据库连接池、jvm字符串常量池
3.结合composite,如图形组合
责任链 responsibility-chain
单向链
验证用户是否有权限时,要依次经过多个不同类型权限验证(AuthHandler);
某一个验证有权限时就停止同时返回true,直到最后一个验证器。
时序图:
sequenceDiagram autonumber AuthHandler1-->>AuthHandler2: UserSubject AuthHandler2-->>AuthHandler3: UserSubject
类图:
classDiagram class UserSubject UserSubject: +userId UserSubject: +userType UserSubject: +group... class AuthHandler <> AuthHandler AuthHandler: +doValidate(UserSubject userSubject) boolean AuthHandler1 ..|> AuthHandler : impl AuthHandler2 ..|> AuthHandler : impl AuthHandler3 ..|> AuthHandler : impl class AuthHandlerChain AuthHandlerChain: +authHandlerList List AuthHandlerChain: +addAuthHandler(AuthHandler authHandler) AuthHandlerChain AuthHandlerChain: +doValidate(UserSubject userSubject) boolean AuthHandlerChain ..|> AuthHandler : impl class Main Main: authHandlerChain.add(authHandler1).add(authHandler2).add(authHandler3) Main: authHandlerChain.doValidate(userSubject)
双向链
例如,tomcat的 Filter/FilerChain , SpringMVC的 HandlerInterceptor
时序图
sequenceDiagram autonumber Filter1-->>Filter2: request Filter2-->>Filter3: request Filter3->>Servlet: request Servlet->>Filter3: response Filter3-->>Filter2: response Filter2-->>Filter1: response
类图:
classDiagram class Filter <> Filter Filter: +doFilter(request, response, filterChain) class FilterChain FilterChain: -p int FilterChain: +doFilter(request, response, filterChain) Filter1 ..|> Filter : impl Filter2 ..|> Filter : impl
代理模式
静态代理
通过代理类去调用代理对象方法
classDiagram class Movable <> Movable Movable: +doMove() class Tank Tank: +doMove() Tank ..|> Movable : impl class TankLogProxy TankLogProxy: -m:Movable TankLogProxy: +doMove() TankLogProxy ..|> Movable : impl class TankTimeProxy TankTimeProxy: -m:Movable TankTimeProxy: +doMove() TankTimeProxy ..|> Movable : impl class Person Person: -name Person: +dirveTank()
动态代理
静态代理缺点:Proxy类需要明确实现Movable接口,不方便切换为其他类型。
如,已经实现好的一个TankLogProxy来打印日志,要想给或者Person也打印日志的话,需要重新实现LogProxy了.
使用jdk动态代理实现:被代理类要通过接口实现
classDiagram class Movable <> Movable Movable: +doMove() class Tank Tank: +doMove() class Person Person: -name Person: +eat() Person: +doMove() class LogProxy LogProxy: -target Object LogProxy: invoke(Object proxy, Method method, Object[] args) Object Tank ..|> Movable : impl Person ..|> Movable : impl LogProxy ..|> InvocationHandler : impl Person o-- LogProxy Tank o-- LogProxy
cglib动态代理实现:被代理接口不需要接口
AOP
spring, aspect oriented programming 面向切面编程
切面:一组代理对象,组成一个切面
切入点:被调用的一个或多个方法,组成一个切入点
织入:从切入点出插入切面的操作,叫织入
通过接口实现的类 ==> jdk动态代理 ==》动态生成代理类,通过代理类来调用方法执行
被代理类(注意不能为final) ==> cglib(asm) ==》动态生成被代理的子类,通过子类来执行方法
迭代器(Iterator)
Array
LinkedList
Collection
Iterator ==>
hasNext():boolean
next():Object
访问者模式(Visitor)
适合内部结构固定的模型
AST(abstract syntex tree 抽象语法树)
Tomcat(server.xml)
asm(class)
构造器(builder)
分步构造一个复杂对象,每个构造器构造复杂对象的一部分,最好拼接起来
classDiagram class Product Product: +part1 Product: +part2 Product: +part3 class Builder <> Builder Builder: +buildPart1() Builder Builder: +buildPart2() Builder Builder: +buildPart3() Builder Builder: +build() Product class SimpleBuilder SimpleBuilder: -product Product SimpleBuilder: +buildPart1() Builder SimpleBuilder: +buildPart2() Builder SimpleBuilder: +buildPart3() Builder SimpleBuilder: +build() Product class ComplextBuilder ComplextBuilder: -product Product ComplextBuilder: +buildPart1() Builder ComplextBuilder: +buildPart2() Builder ComplextBuilder: +buildPart3() Builder ComplextBuilder: +build() Product SimpleBuilder ..|> Builder : impl ComplextBuilder ..|> Builder : impl Builder ..> Product : create
适配器模式(adapter)
适配两种不同的类型
classDiagram class FileInputStream FileInputStream: +read() class InputStreamReader InputStreamReader: +read() class BufferedReader BufferedReader: +readLine() FileInputStream -- InputStreamReader InputStreamReader -- BufferedReader FileInputStream .. BufferedReader : 不能直接访问
桥接模式(bridge)
m-n m/n都有多种的时候,使用桥接模式,避免类爆炸
classDiagram class MClazz MClazz: +NClazz MClazz: +get() MNClazz class NClazz1 NClazz1: +exec1() class NClazz2 NClazz2: +exec2() class NClazz3 NClazz3: +exec3() NClazz1 ..|> NClazz : extends NClazz2 ..|> NClazz : extends NClazz3 ..|> NClazz : extends MClazz *-- NClazz : Composition
命令模式(command)
classDiagram class Command <> Command Command: -content StringBuilder Command: +redo() Command: +undo() InsertCommand --|> Command RedoCommand --|> Command UndoCommand --|> Command
- 多个命令组成大的命令:composite(组合)
- 多次redo命令:chain responseribility(责任链)
- trasaction回滚:记忆
原型模式(prototype)
Object.clone() ==> Cloneable
- 浅copy:引用类型只copy对象地址
- 深copy:被引用对象实现cloneable接口,组合对象clone方法调用成员对象的clone对象
哪些对象需要注意clone
- 基本数据类型 不需要
- String 不需要,都是使用的常量池
- StringBuilder/StringBuffer 也需要复制一份
- 引用对象 必须实现clone方法
备忘录模式(memento)
记录快照 –> 对象序列化(反序列化)
serizliable
transient
模板方法(TemplateMethod)
钩子函数
状态模式(state)
swatch case ==转换==> 多个子类
- 有限状态机
Thread state
解释器(Intepreter)
动态脚本解释
6大设计原则
solid稳定的 记忆首字母
单一原则(Single Responsibility Principle)
一个类或者一个方法只负责一项职责,尽量做到类的只有一个行为原因引起变化
开闭原则(open closed principle)
用抽象构建架构,用实现扩展原则
里氏替换原则(LSP liskov substitution principle)
子类可以扩展父类的功能,但不能改变原有父类的功能
迪米特原则(law of demeter LOD)
最少知道原则,尽量降低类与类之间的耦合;
一个对象应该对其他对象有最少的了解
接口隔离(interface segregation principle)
建立单一接口;(扩展为类也是一种接口,一切皆接口)
定义:
a.客户端不应该依赖它不需要的接口;
b.类之间依赖关系应该建立在最小的接口上;
简单理解:复杂的接口,根据业务拆分成多个简单接口;(对于有些业务的拆分多看看适配器的应用)
【接口的设计粒度越小,系统越灵活,但是灵活的同时结构复杂性提高,开发难度也会变大,维护性降低】
依赖倒置原则(dependence inversion principle)
面向接口编程;(通过接口作为参数实现应用场景)
抽象就是接口或者抽象类,细节就是实现类
含义:
上层模块不应该依赖下层模块,两者应依赖其抽象;
抽象不应该依赖细节,细节应该依赖抽象;
通俗点就是说变量或者传参数,尽量使用抽象类,或者接口;
【接口负责定义public属性和方法,并且申明与其他对象依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑】