设计原则:
1:单一原则:接口职责单一
2:开闭原则:扩展开,修改闭
3:里氏替换原则:抽象接口代替组合绑定
4:隔离原则:特殊接口隔离,不修改原有接口规则
5:依赖倒置原则:底层及顶层不直接依赖中间层,将中间层替换成抽象接口层
6:迪米特法则:高内聚底耦合,增加中间处理者
设计模式
单例模式:此模式保证某个类在运行期间,只有一个实例对外提供服务,而这个类被称为单例类
1:保证一个类只有一个实例
2:为改实例提供一个全局访问节点
饿汉式:在类加载期间初始化静态实例,保证instance实例的创建时线程安全的(实例在类加载时实例化,JVM保证线程安全)
1:不支持延迟加载实例(懒加载),类加载比较慢,但获取实例对象比较快
2:该对象足够大的话,而一直未使用就会造成内存空间的浪费
懒汉式:只有调用getInstance方法时,才创建对象。多线程下使用同步锁synchronize + voliate + DCL保证线程安全
静态内部类:根据静态内部类的特性(外部类的加载不影响内部类),同时解决了按需加载,线程安全的问题,实现简洁
1:在静态内部类里创建单例,在装载该内部类时才会去创建单例
2:线程安全:类由JVM加载,而JVM只会加载一遍,保证只有一个单例
反射对于单例的破坏:
反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意方法和属性。这种动态获取信息以及动态调用对象方法的功能称为JAVA语言的反射机制。
反射机制过于强大,它可以通过setAccessible()来修改构造器,字段,方法的可见性。单例模式的构造方法是私有的如果将其可见性设为public,那么将无法控制对象的创建。
解决:在单例类的构造方法中,添加判断instance != null时,直接抛出异常
序列化对于单例的破坏:序列化会通过反射调用无参的构造方法创建一个新的对象
通过Singleton的序列化与反序列化得到的对象是一个新的对象,破坏了Singleton的单例性。
解决:在Singleton类中定义readResolve,并在该方法中指定要返回的对象的生成策略,就可以解决问题,程序会判断是否有readResolve方法,如果存在就在执行该方法,不存在就创建一个对象
枚举:使用枚举时,构造方法会被自动调用,利用这一特性也可实现单例:默认枚举实例的创建时线程安全的,即使反序列化也不会生成新的实例,任何情况下都是一个单例(反射破坏对枚举无效)
工厂模式:在创建对象时不会对客户端暴露创建的逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
简单工厂模式(静态工厂方法模式):通过使用静态方法接受不同的参数来返回不同的实例对象
实现方式:定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例具有共同的父类或接口。
使用场景:需要创建的对象较少,客户端不关心对象的创建过程
工厂方法模式:封装对象创建的过程,提升创建对象方法的可复用性
建造者模式:工厂模式用来不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。建造者模式是用来创建一种类型的复杂对象,通过设置不同的可选参数,定制化地创建不同的对象
原型模式:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。如果创建对象的成本比较大,如对象中的数据是经过复杂计算才能得到,或者需要从RPC接口或者数据库等比较慢的IO中获取,这种情况可使用原型模式,从其他已有的对象中进行拷贝。
浅克隆(BeanUtils.cloneBean(Object obj) BeanUtils.copyProperties(s,T)):被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其它对象的引用仍然指向原来的对象(克隆对象与原型对象共享引用数据类型变量)
深克隆(SerializationUtils.clone(T object)):把要复制的对象所引用的对象都复制了一遍
代理模式:提供对象的替代品或其占位符,代理控制着对于原对象的访问,并允许将请求提交给对象的前后进行一些处理。 代理模式中引入了一个新的代理对象,代理对象在客户端对象和目标对象之间起到了中介的作用,它去掉客户不能看到的内容和服务或者增加客户需要的额外的新服务。