设计模式目的
提高软件的可维护性、通用性、可扩展性;并降低软件复杂度
四大发明之活字印刷
可维护
可复用
可扩展
灵活性
开发原则
单一职责原则
功能尽量单一
根据业务复杂度:可以在方法层面实现职责单一,也可以在类层面实现职责单一
依赖倒转原则
抽象不应该依赖细节,细节应该依赖于抽象
面向接口编程,不要对实现编程
里氏代换原则
子类型必须能够替换掉父类型
所有引用基类的地方必须能够透明的使用子类对象
实际是尽量避免子类对父类方法的重写
如果必须使用:则可通过聚合、组合、依赖等方案
开放封闭原则
对扩展开放
对更改封闭
迪米特法则
即最少知道原则(一个类对自己依赖的类知道的越少越好。无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类)
只要两个对象之间有耦合关系,即称为朋友关系(耦合关系:组合、聚合、依赖、关联)
更简单的定义:只与【直接】朋友通信
迪米特法则的核心是降低耦合关系,但不能完全无耦合关系
合成复用原则
降低耦合性
尽量使用合成/聚合的方式,而不是使用继承
接口隔离??
创建型
Singleton:单例模式
在软件系统中,保证一个类仅有一个实例,并提供一个全局访问点
创建方式
饿汉模式
静态常量
静态代码块
优点:在类装载时完成实例化,操作简单,避免线程同步问题;
缺点:没有达到lazy loader效果,可能造成内存浪费
懒汉模式
线程不安全
优点:起到lazy loader效果,不浪费内存;【在单线程下才能使用】
缺点:线程不安全
实际开发中不建议使用
线程安全(同步方法)
优点:起到lazy loader作用,不浪费内存,同时解决线程安全问题
缺点:因为每次获取实例时都要进行同步。性能低下
实际开发中不建议使用
线程安全(同步代码块)
缺点:起不到线程安全作用
直接不能用
双重校验
对象定义时添加volitile关键字
同步代码块出进行双重检查
public static Object getInstance(){}
优点:既保证线程安全,也保证了效率。
逻辑说明:先判断是否为null,避免了同步延时;在进入同步时再判断是否已经实例化,避免创建多个实例
静态内部类
特点:当外部类被装载时,静态内部类不会被装载;当内部类被调用时内部类才会被装载(而且只装载一次,因此是线程安全的)
类的静态属性只会在第一次加载时初始化,JVM保证了线程的安全性
枚举
优点:不仅避免了多线程问题,而且还避免反序列化创建新的对象
实例:Hibernate中的SessionFactory、JDK中的Runtime(饿汉模式)
使用场景:需要频繁的创建和销毁的对象,对象创建比较耗时;如:经常使用的对象、工具类对象、频繁访问数据库或文件的对象等
工厂模式
简单工厂模式
优点:工厂类中包含了必要的逻辑判断,根据客户端条件动态实例化相关类;对客户端来说,去除了与具体产品的依赖。
实例:JDK中Calendar.getInstance
工厂方法模式
定义:定义一个用于创建对象的抽象方法,让子类决定实例化的类,工厂方法使得一个类的实例化延迟到其子类中。
父类创建一个抽象方法由子类实现
抽象工厂模式
提供创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类
Prototype:原型模式
定义:用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象
对象实现接口Cloneable中的clone方法
优点:
1、一般在初始化信息不发生变化的情况下,克隆是最好的方式,既隐藏了对象创建的细节,有大大提高性能。
2、不用重新初始化对象,而是动态的获取对象运行时的状态。
浅复制与深复制:如果类型是值类型,则逐个复制;若为引用类型,则复制引用地址,那么原始对象与复本引用同一对象(即副本改变则原对象改变)。
深拷贝实现
clone方式
Object clone = super.clone();
序列化实现
相对于clone方式,避免了对象中多个引用类型的遍历处理
Builder:建造者模式
也叫生成器模式
定义:将一个复杂对象的创建与其表示分离,使其同样的构建过程可以创建不同的表示。
应用场景:当创建复杂对象的算法应独立于实现过程
实例:jdk中StringBuilder
结构型
Adapter:适配器模式
定义:将一个类的接口转换成客户希望的另外一个接口;使不兼容的接口通过适配可兼容工作
适配器类型:类适配器、接口适配器、对象适配器
实例:SpringMVC中的HandlerAdapter
DispatchServlet根据请求controller类型获取对应的HandleAdapter,然后根据handleAdapter调用具体的controller实现
参考:姚明需要翻译
Bridge:桥接模式
定义:将抽象部分与他的实现部分相分离,使他们都可以独立的变化
基于类的最少设计原则
实例:JDBC
参考:手机与软件
Decorator:装饰模式
动态的给一个对象添加额外的职责,就增加功能来说,比生成子类更灵活
实例:FilterInputStream
Composite:组合模式
定义:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
应用场景:体现部分与整体层次的机构时,以及希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时。
实例:HashMap
参考:办公OA系统
Facade:外观模式
为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用
也称过程模式
实例:mybatis
Flyweight:享元模式
定义:运用共享技术有效的支持大量细粒度对象
优点:可以避免大量非常相似类的开销。在程序设计中有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了参数基本都是相同的,有时就能能够大幅度的减少需要实例化的类的数量。如果能把那些参数移到类实例的外面,在方法调用时将他们传递过来,就可以通过共享大幅度的减少单个实例的数目。
认清内部状态外部状态
参考:网站共享、基本类型包装类、共享池等(数据库连接池、String常量池等)
jdk实例:Integer中valueOf方法-128~127
Proxy:代理模式
为其他对象提供一种代理以控制对这个对象的访问
优点:对功能进行增强
动态代理:使用反射和字节码技术,在运行期创建指定接口或类的子类,以及其实例对象的技术。通过该技术可以无侵入的对代码进行增强
jdk动态代理
cglib动态代理
基于ASM的字节码生成库,允许在运行时对字节码进行修改和动态生成。
被代理类不能为final类
代理类实现MethodIntercept,并实现intercept方法;获取实例getInstance{Enhance eh = new Enhance();eh.setSuperClass;eh.setCallback;eh.create}
几种代理变体:
1、远程代理
2、虚拟代理
3、安全代理
4、智能指引
行为型
Strategy:策略模式
定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到客户的使用
策略模式的Strategy类层次为Context定义了一系列可供重用的算法或行为;继承有助于析取出这些算法中的公共功能
State:状态模式
定义:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类
目的:当控制一个对象的状态转换的条件表达式过于复杂时的情况,把状态的判断逻辑转移到表示不同状态的一系列类中,把复杂的判断逻辑简单化
在多种状态转换时,对外输出不同的行为。状态与行为一一对应,状态见可相互转化
Template:模板方法模式
定义:定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
应用场景:当我们要完成某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时,通常采用模板方法模式
参考:抄试卷、类的继承等
Observer:观察者模式
Iterator:迭代器模式
定义:提供一种方法顺序阀访问一个聚合对象中各个元素,而又不暴露内部表示
分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露内部集合的结构,又可以让外部代码透明的访问集合的内部数据
参考:公交乘务员售票
Chain of Responsibility:责任链模式
OA系统的审批流程
springmvc中请求处理流程
Command:命令模式
定义:将一个请求封装为一个对象,从而使你可用不同的请求对客户参数化,对请求排队或记录日志,以及支持可撤销操作
Memento:备忘录模式
定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存该状态。这样以后就可以将该对象恢复到原先保存的状态。
应用场景:电脑设置还原点
Visitor:访问者模式
定义:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
将数据结构与数据操作分离
缺点:不利于维护
Mediator:中介模式
定义:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示的相互引用,从而是耦合松散,而且可以独立的改变他们之间的交互。
子主题 2
Interpreter:解释器模式
定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器。这个解释器使用该表示来解释语言中的句子
应用场景:正则表达式
UML类图
语言语法
依赖
依赖:虚线箭头
实现【依赖特例】
表达方式:空心三角形+虚线
泛化(即继承)【依赖特例】
表达方式:空心三角形+实线
关联【依赖特例】
表达方式:实线箭头
聚合
局部与整体可以分割
表达方式:空心菱形+实线箭头
组合
局部与整体不可分割
表达方式:实心菱形+实线箭头