Skip to content

coldcaffe/Pattern

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

10 Commits

Repository files navigation

#Java设计模式及常见问题梳理总结

##单例设计模式总结 知识重点: 1.私有化构造器 2.保证线程安全 3.延迟加载 4.防止序列化和反序列化破坏单例 5.防止反射攻击破坏单例

单例的优点: 1.在内存中只有一个实例,减少了内存开销 2.可以避免对资源的多重占用 3.设置全局访问点,严格控制访问

单例的缺点: 1.没有接口,扩展困难 2.如果要扩展单例对象,只能修改代码没有其他途径(不符合开闭原则)

##原型模式(构建型) 适用场景: 1.类初始化消耗资源过多 2.new产生对象过程非常繁琐(数据准备,访问权限等) 3.构造函数比较复杂 4.循环体中产生大量对象导致可读性下降时

成熟案例: BeanUtils.copy(),JSON.parseObject(),Guava...

总结: 是快速构建对象的方法总结,(1)简单工厂将getter,setter封装到某个方法中,(2)JDK提供实现Cloneable接口进行快速复制 Spring中一般都是浅克隆,原型模式与单例模式存在本质上的冲突(如果必须实现共存可以通过实现io中readResolve方法等处理)

缺点: 1.必须配备克隆(或者可拷贝)方法 2.对克隆复杂对象或对克隆对象进行复杂改造时易带来风险 3.深拷贝,浅拷贝要运用得当

##代理模式(结构型) 优点: 1.为其他对象提供一种代理以控制对这个对象的访问(保护对象,增强对象) 2.代理对象在客服端和目标对象间起到中介作用(隔离) 3.一定程度上降低了系统的耦合程度,易于拓展

缺点: 1.会造成系统设计中类的数目增加 2.在客户端和目标对象间增加了代理对象,会造成请求处理速度变慢 3.增加了系统复杂度

原理: JDK动态代理: 1.拿到被代理类(必须实现接口)的引用,并且获取它的所有接口(反射获取) 2.JDK Proxy类重新生成一个新的类,实现了被代理类所有接口的方法 3.动态生成Java代码,把增强逻辑加入到新生成代码中 4.编译生成新的Java代码的class文件 5.加载并运行新的class,得到的类就是全新生成的类(代理类"$Proxy0",序号可自增)

CGLib代理: 使用ASM框架写Class字节码 

实例: Spring框架中AOP实现

思考: 代理模式应用场景及实现原理(实现数据源动态切换), 静态代理和动态代理的区别(静态需显示声明--但不符合开闭原则,动态代理则是动态配置和替换被代理对象), CGLib和JDK Proxy的根本区别(cglib通过继承关系实现,而jdk方式需目标类实现接口) (1)cglib覆盖父类方法进行实现(任意普通类都可),生成逻辑 更复杂,效率和调用效率更高生成一个包含了所有逻辑的FaseClass,不需再反射调用(但不能代理final的方法) (2)JDK Proxy生成代理逻辑简单(直接写Class字节码),执行效率相对要低,每次都要反射动态调用 为什么JDK代理中对接口总数限制在65535以下?(JVM在class文件定义时,规定interface的类型是u2,2个字节,16位,那么最多支持2的16次方-1,也就是65535,可参考: https://www.baidu.com/s?ie=UTF-8&wd=JVM%E5%9C%A8class%E6%96%87%E4%BB%B6%E5%AE%9A%E4%B9%89%E6%97%B6%EF%BC%8C%E8%A7%84%E5%AE%9Ainterface%E7%9A%84%E7%B1%BB%E5%9E%8B%E6%98%AFu2)

##委派模式(行为型) 负责任务的调度和分配任务,可以看做一种特殊情况下的静态代理的全权代理,但代理模式注重过程,委派模式注重结果 不属于GOF23种模式之一

实例: Spring中Delegate或Dispatcher在类中包含的都是委派模式

##策略模式() 定义了算法家族,分别封装使之可以相互替换,此模式让算法的 变化不会影响到算法的用户(可以避免多重分支的if...else和switch语句) 算法确定,注重选择及结果

实例: JDK中Comparator接口的compare()实现,Spring中IstantiationStrategy(选择jdk还是cglib实现类,单例还是多例...)

优点: 1.符合开闭原则,避免了使用多重条件转移语句,如if...else...,switch语句等 2.可以提高算法的保密性和安全性

缺点: 1.客户端必须知道所有的策略,并且自行决定使用哪一个策略类 2.代码中会产生非常多策略类,增加维护难度

##模板模式(行为型) 结构与策略模式有类似,但是注重流程,算法可根据实际需要进行变更(如不同的List实现类中get方法有实现区别)

适用场景: 1.一次性实现算法不变部分,并将可变行为留给子类来实现 2.各子类中公共行为被提取出来并集中到一个公共父类中从而避免代码重复

优点: 1.提高代码复用性和拓展性 2.符合开闭原则

缺点: 1.类的数目增加,间接的增加了系统实现的复杂度 2.继承关系自身缺点,如果父类增加新的抽象方法,子类都必须去新增实现

实例: List的子类实现中get()的具体实现,Httpservlet的子类中service()实现,Spring的jdbcTemplate

##适配器模式(结构型) 指将一个类的接口转换成客户期待的另一个接口,使原本不兼容的类可以一起工作(类似变压器转接头)

适用场景: 1.已存在类,方法和需求不匹配的情况 2.不是软件设计阶段考虑的设计模式,一般用于软件后期维护

优点: 1.能提高类的透明性和复用,现有的类复用但不需要改变 2.目标类和适配器类解耦,提高程序的拓展性 3.在很多业务场景中符合开闭原则

缺点: 1.在编写过程中需全面考虑,否则会导致系统的复杂性 2.增加了代码阅读难度,降低了代码可读性,使用过多会使系统凌乱

实例: Spring aop中dispatcherServelet中对handlerAdapter的调用(getHandlerAdapter)

##查疑补缺记录 1.总结内部类执行逻辑 2.单例中实现ObjectInputStream反射调用readResolve方法以保证单例不被序列化破坏的原理及流程 3.后续需补充序列化及反序列化对单例破坏的用例 4.后续补充发令枪多线程测试类 5.理解枚举单例中防范序列化及反射破坏单例的实现原理(借助jad反编译源码,javap用于反编译字节码,需区分清楚)

About

Java设计模式及常见问题梳理总结

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages