Skip to content

dolojia/design-patterns

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JAVA设计模式

软件架构设计七大原则

  • 开闭原则
    • 开闭原则(Open-ClosedPrinciple,OCP)是指一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。所谓的开闭,也正是对扩展和修改两个行为的一个原则。强调的是用抽象构建框架,用实现扩展细节。可以提高软件系统的可复用性及可维护性。开闭原则,是面向对象设计中最基础的设计原则。它指导我们如何建立稳定灵活的系统,例如:我们版本更新,我尽可能不修改源代码,但是可以增加新功能。
  • 依赖倒置原则
    • 依赖倒置原则(DependenceInversionPrinciple,DIP)是指设计代码结构时,高层模块不应该依赖底层模块,二者都应该依赖其抽象。抽象不应该依赖细节;细节应该依赖抽象。通过依赖倒置,可以减少类与类之间的耦合性,提高系统的稳定性,提高代码的可读性和可维护性,并能够降低修改程序所造成的风险。
  • 单一职责原则
    • 单一职责(SimpleResponsibilityPinciple,SRP)是指不要存在多于一个导致类变更的原因。假设我们有一个Class负责两个职责,一旦发生需求变更,修改其中一个职责的逻辑代码,有可能会导致另一个职责的功能发生故障。这样一来,这个Class存在两个导致类变更的原因。如何解决这个问题呢?我们就要给两个职责分别用两个Class来实现,进行解耦。后期需求变更维护互不影响。这样的设计,可以降低类的复杂度,提高类的可读性,提高系统的可维护性,降低变更引起的风险。总体来说就是一个Class/Interface/Method只负责一项职责。
  • 接口隔离原则
    • 接口隔离原则(InterfaceSegregationPrinciple,ISP)是指用多个专门的接口,而不使用单一的总接口,客户端不应该依赖它不需要的接口。这个原则指导我们在设计接口时应当注意一下几点:1、一个类对一类的依赖应该建立在最小的接口之上。2、建立单一接口,不要建立庞大臃肿的接口。3、尽量细化接口,接口中的方法尽量少(不是越少越好,一定要适度)。接口隔离原则符合我们常说的高内聚低耦合的设计思想,从而使得类具有很好的可读性、可扩展性和可维护性。我们在设计接口的时候,要多花时间去思考,要考虑业务模型,包括以后有可能发生变更的地方还要做一些预判。所以,对于抽象,对业务模型的理解是非常重要的。
  • 迪米特法则
    • 迪米特原则(LawofDemeterLoD)是指一个对象应该对其他对象保持最少的了解,又叫最少知道原则(LeastKnowledgePrinciple,LKP),尽量降低类与类之间的耦合。迪米特原则主要强调只和朋友交流,不和陌生人说话。出现在成员变量、方法的输入、输出参数中的类都可以称之为成员朋友类,而出现在方法体内部的类不属于朋友类。现在来设计一个权限系统,Boss需要查看目前发布到线上的课程数量。这时候,Boss要找到TeamLeader去进行统计,TeamLeader再把统计结果告诉Boss。
  • 里氏替换原则
    • 里氏替换原则(LiskovSubstitutionPrinciple,LSP)是指如果对每一个类型为T1的对象o1,都有类型为T2的对象o2,使得以T1定义的所有程序P在所有的对象o1都替换成o2时,程序P的行为没有发生变化,那么类型T2是类型T1的子类型。定义看上去还是比较抽象,我们重新理解一下,可以理解为一个软件实体如果适用一个父类的话,那一定是适用于其子类,所有引用父类的地方必须能透明地使用其子类的对象,子类对象能够替换父类对象,而程序逻辑不变。根据这个理解,我们总结一下:引申含义:子类可以扩展父类的功能,但不能改变父类原有的功能。1、子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。2、子类中可以增加自己特有的方法。3、当子类的方法重载父类的方法时,方法的前置条件(即方法的输入/入参)要比父类方法的输入参数更宽松。4、当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的输出/返回值)要比父类更严格或相等。 使用里氏替换原则有以下优点:1、约束继承泛滥,开闭原则的一种体现。2、加强程序的健壮性,同时变更时也可以做到非常好的兼容性,提高程序的维护性、扩展性。降低需求变更时引入的风险。
  • 合成复用原则
    • 合成复用原则(Composite/AggregateReusePrinciple,CARP)是指尽量使用对象组合(has-a)/聚合(contanis-a),而不是继承关系达到软件复用的目的。可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少。继承我们叫做白箱复用,相当于把所有的实现细节暴露给子类。组合/聚合也称之为黑箱复用,对类以外的对象是无法获取到实现细节的。要根据具体的业务场景来做代码设计,其实也都需要遵循OOP模型。

Spring中用到的设计模式

  • 工厂模式BeanFactory
  • 装饰器模式BeanWrapper
  • 代理模式AopProxy单例模式
  • ApplicationContext
  • 委派模式DispatcherServlet
  • 策略模式HandlerMapping
  • 适配器模式HandlerApdapter
  • 模板方法模式JdbcTemplate
  • 观察者模式ContextLoaderListener

工厂模式

单例模式的应用场景 单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并 提供一个全局访问点。单例模式是创建型模式。

  • 简单工厂模式 简单工厂模式(SimpleFactoryPattern)是指由一个工厂对象决定创建出哪一种产品类的实例。
  • 工厂方法模式 工厂方法模式(FatoryMethodPattern)是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。
  • 抽象工厂模式 抽象工厂模式(AbastractFactoryPattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。

单例模式

  • 饿汉式单例 饿汉式单例是在类加载的时候就立即初始化,并且创建单例对象。绝对线程安全,在线 程还没出现以前就是实例化了,不可能存在访问安全问题。 优点:没有加任何的锁、执行效率比较高,在用户体验上来说,比懒汉式更好。 缺点:类加载的时候就初始化,不管用与不用都占着空间,浪费了内存,
  • 懒汉式单例 懒汉式单例的特点是:被外部类调用的时候内部类才会加载
  • 注册式单例

注册式单例又称为登记式单例,就是将每一个实例都登记到某一个地方,使用唯一的标 识获取实例。注册式单例有两种写法:一种为容器缓存,一种为枚举登记。

  • threadlocal式单例,伪单例模式,线程内单例(保证同一个线程内是单例的) ThreadLocal 不能保证其 创建的对象是全局唯一,但是能保证在单个线程中是唯一的,天生的线程安全。 ThreadLocal 将所有的对象全部放在 ThreadLocalMap 中,为每个线程都提供一个对象

原型模式

原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过拷贝这些 原型创建新的对象。 原型模式主要适用于以下场景: 1、类初始化消耗资源较多。 2、new 产生的一个对象需要非常繁琐的过程(数据准备、访问权限等) 3、构造函数比较复杂。 4、循环体中生产大量对象时。

代理模式

  • 静态代理 动态代理和静态对比基本思路是一致的,只不过动态代理功能更加强大,随着业务的扩 展适应性更强。
  • 动态代理
    • JDK动态代理
    • CGLib动态代理 CGLib 代理的目标对象不需要实现任何接口,它是通过动态继承目标对象 实现的动态代理 CGLib 动态代理执行代理方法效率之所以比 JDK 的高是因为 Cglib 采用了 FastClass 机 制,它的原理简单来说就是:为代理类和被代理类各生成一个 Class,这个 Class 会为代 理类或被代理类的方法分配一个 index(int 类型)。这个 index 当做一个入参,FastClass 就可以直接定位要调用的方法直接进行调用,这样省去了反射调用,所以调用效率比 JDK
  • 动态代理通过反射调用高。 CGLib 和 JDK 动态代理对比 1.JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。 2.JDK 和 CGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM 框架写 Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。 3.JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法, CGLib 执行效率更高。
  • 静态代理和动态的本质区别
    • 1、静态代理只能通过手动完成代理操作,如果被代理类增加新的方法,代理类需要同步 新增,违背开闭原则。
    • 2、动态代理采用在运行时动态生成代码的方式,取消了对被代理类的扩展限制,遵循开 闭原则。
    • 3、若动态代理要对目标类的增强逻辑扩展,结合策略模式,只需要新增策略类便可完成, 无需修改代理类的代码。
  • 代理模式的优缺点
    • 1、代理模式能将代理对象与真实被调用的目标对象分离。
    • 2、一定程度上降低了系统的耦合度,扩展性好。
    • 3、可以起到保护目标对象的作用。
    • 4、可以对目标对象的功能增强。 缺点的:
    • 1、代理模式会造成系统设计中类的数量增加。
    • 2、在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。
    • 3、增加了系统的复杂度。

委派模式

委派模式(Delegate Pattern)的基本作用就是负责任务的调 度和分配任务,跟代理模式很像,可以看做是一种特殊情况下 的静态代理的全权代理,但是代理模式注重过程,而委派模式 注重结果。

策略模式

策略模式(Strategy Pattern)是指定义了算法家族、分别封 装起来,让它们之间可以互相替换,此模式让算法的变化不会 影响到使用算法的用户。

模版模式

  • 模板模式通常又叫模板方法模式(Template Method Pattern)是指定义一个算法的骨架,并允许子类为一个或者 多个步骤提供实现。
  • 模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。
    • 1、一次性实现一个算法的不变的部分,并将可变的行为留给 子类来实现。
    • 2、各子类中公共的行为被提取出来并集中到一个公共的父类 中,从而避免代码重复。

适配器模式

  • 适配器模式(Adapter Pattern)是指将一个类的接口转换成 客户期望的另一个接口,使原本的接口不兼容的类可以一起工 作。
    • 1、已经存在的类,它的方法和需求不匹配(方法结果相同或相似) 的情况。
    • 2、适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护, 由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决 方案。

装饰器模式

  • 装饰者模式(Decorator Pattern)是指在不改变原有对象的 基础之上,将功能附加到对象上,提供了比继承更有弹性的替 代方案(扩展原有对象的功能)。

  • 1、用于扩展一个类的功能或给一个类添加附加职责。

  • 2、动态的给一个对象添加功能,这些功能可以再动态的撤销。

  • 3、优点

  • 1、装饰者是继承的有力补充,比继承灵活,不改变原有对象 的情况下动态地给一个对象扩展功能,即插即用。

  • 2、通过使用不同装饰类以及这些装饰类的排列组合,可以实 现不同效果。

  • 3、装饰者完全遵守开闭原则。

    装饰者模式 适配器模式
    形式 是一种非常特别的适配器模式 没有层级关系,装饰器模式有层级关系
    定义 装饰者和被装饰者都实现同一个接 口,主要目的是为了扩展之后依旧保留 OOP 关系 适配器和被适配者没有必然的联系,通 常是采用继承或代理的形式进行包装
    关系 满足 is-a 的关系 满足 has-a 的关系
    功能 注重覆盖、扩展 注重兼容、转换
    设计 前置考虑 后置考虑

观察者模式

  • 观察者模式(Observer Pattern)定义了对象之间的一对多 依赖,让多个观察者对象同时监听一个主体对象,当主体对象 发生变化时,它的所有依赖者(观察者)都会收到通知并更新。
  • 1、观察者和被观察者之间建立了一个抽象的耦合。
  • 2、观察者模式支持广播通信。

Spring中常用的设计模式

设计模式 一句话归纳 举例
工厂模式(Factory) 单例模式(Singleton) 原型模式(Prototype) 只对结果负责,封装创建过程 BeanFactory、Calendar
代理模式(Proxy) 保证独一无二。 ApplicationContext、Calendar
委派模式(Delegate) 拔一根猴毛,吹出千万个。 ArrayList、PrototypeBean
策略模式(Strategy) 模板模式(Template) 适配器模式(Adapter) 找人办事,增强职责。 ProxyFactoryBean、JdkDynamicAopProxy、CglibAopProxy
装饰器模式(Decorator) 干活算你的(普通员工),功劳 算我的(项目经理)。 DispatcherServlet、BeanDefinitionParserDelegate
观察者模式(Observer) 用户选择,结果统一。 InstantiationStrategy
模板模式(Template) 流程标准化,自己实现定制。 JdbcTemplate、HttpServlet
适配器模式(Adapter) 兼容转换头。 AdvisorAdapter、HandlerAdapter
装饰器模式(Decorator) 包装,同宗同源。 BufferedReader、InputStream、OutputStream、HttpHeadResponseDecorator
观察者模式(Observer) 任务完成时通知。 ContextLoaderListener

Spring中的编程思想总结

Spring思想 应用场景(特点) 一句话归纳
OOP Object Oriented Programming(面向对象编程)用程序归纳总结生活中一切事物。 封装、继承、多态。
BOP Bean Oriented Programming(面向Bean编程)面向Bean(普通的java类)设计程序。 一切从Bean开始。
AOP Aspect Oriented Programming(面向切面编程)找出多个类中 AOP 有一定规律的代码,开发时拆开,运行时再合并。面向切面编程,解耦,专人做专事。 即面向规则编程。 解耦,专人做专事。
IOC nversion of Control(控制反转)将new对象的动作交给Spring管理,并由Spring保存已创建的对象(IOC容器)。 转交控制权(即控制权反转)
DI/DL Dependency Injection(依赖注入)或者Dependency Lookup(依赖查找)依赖注入、依赖查找,Spring不仅保存对象与对象之间的关联关系,注入即赋值,主要三种赋值方式,构造方法、set赋值、直接赋值(反射)

About

JAVA设计模式

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages