设计模式—结构型

主要解决“类或对象的组合或组装”问题;将不同功能代码解耦

结构型模式主要总结了一些类或对象组合在一起的经典结构,这些经典的结构可以解决特定应用场景的问题

代理模式

代理模式的原理与实现

在不改变原始类(或叫被代理类)的情况下,通过引入代理类来给原始类附加功能。 一般情况下,我们让代理类和原始类实现同样的接口。但是,如果原始类并没有定义接口,并且原始类代码并不是我们开发维护的。在这种情况下,我们可以通过让代理类继承原始类的方法来实现代理模式

动态代理的原理与实现

静态代理需要针对每个类都创建一个代理类,并且每个代理类中的代码都有点像模板式的“重复”代码,增加了维护成本和开发成本 对于静态代理存在的问题,我们可以通过动态代理来解决。我们不事先为每个原始类编写代理类,而是在运行的时候动态地创建原始类对应的代理类,然后在系统中用代理类替换掉原始类 动态代理的实现:Java 语言本身就已经提供了动态代理的语法(实际上,动态代理底层依赖的就是 Java 的反射语法)

代理模式的应用场景

业务系统的非功能性需求开发,比如:监控、统计、鉴权、限流、事务、幂等、日志;将这些附加功能与业务功能解耦,放到代理类统一处理,让程序员只需要关注业务方面的开发 RPC 框架也可以看作一种远程代理模式,通过远程代理,将网络通信、数据编解码等细节隐藏起来。客户端在使用 RPC 服务的 时候,就像使用本地函数一样,无需了解跟服务器交互的细节。RPC 服务的开 发者也只需要开发业务逻辑,就像开发本地使用的函数一样,不需要关注跟客户端的交互细 节 代理模式在缓存中的应用

spring动态代理概念

代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能,这是它跟装饰器模式最大的不同

桥接模式

JDBC概念:Java DataBase Connectivity(Java数据库连接技术)

JDBC驱动的原理

1、加载数据库驱动:使用Class.forName方法,调用这个方法会加载数据库驱动com.MySQL.jdbc.driver。 2、获取数据库连接DriverManager.getConnection()。这个方法主要调用driver的connect()方法 3、然后利用Connection对象创建Statement,发送sql语句访问数据库 JDBC设计理念:JDBC就是对于java编码来说,在应用程序和数据库之间的一个中间层 API有了中间层JDBC,你就可以面向JDBC API进行编程,不需要关注底层数据库细节。 桥接模式的目的是将接口部分和实现部分分离,从而让它们可以较为容易、也相对独立地加以改变

装饰者模式

java IO的源码

Java IO的设计理念:Java为了使用尽量少的类提供尽量强大的io功能,在io设计的时候采用了装饰模式。装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

装饰器模式和Python装饰器概念的区别

装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承。它主要的作用是给原始类添加增强功能 python中装饰器是对装饰模式的一个更宽泛的应用,不只能够应用于类,也能应用于函数、类方法和类属性

代理模式 VS 装饰者模式

代理模式中,代理类附加的是跟原始类无关的功能 在装饰器模式中,装饰器类附加的是跟原始类相关的增强功能 装饰者模式在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的嵌套使用

适配器模式

概念:这个模式就是用来做适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作

两种实现方式

类适配器使用继承关系来实现 对象适配器使用组合关系来实现

5种常见的应用场景

封装有缺陷的接口设计 统一多个类的接口设计 替换依赖的外部系统 兼容老版本接口 适配不同格式的数据 适配器模式是一种事后的补救策略。适配器提供跟原始类不同的接口,而代理模式、装饰器模式提供的都是跟原始类相同的接口

门面模式

概念:门面模式为子系统提供一组统一的接口,定义一组高层接口让子系统更易用 应用场景 解决易用性问题:门面模式可以用来封装系统的底层实现,隐藏系统的复杂性,提供一组更加简单易用、更高层的接口 解决性能问题:通过将多个接口调用替换为一个门面接口调用,减少网络通信成本,提高 App 客户端的响应速度 解决分布式事务问题:借鉴门面模式的思想,再设计一个包裹这两个操作的新接口,让新接口在一个事务中执行两个 SQL 操作

组合模式

组合模式跟我们之前讲的面向对象设计中的“组合关系(通过组合来组装两个类)”,完全是两码事 组合模式的设计思路,与其说是一种设计模式,倒不如说是对业务场景的一种数据结构和算法的抽象 组合模式,将一组对象组织成树形结构,将单个对象和组合对象都看做树中的节点,以统一处理逻辑,并且它利用树形结构的特点,递归地处理每个子树,依次简化代码实现 使用组合模式的前提在于,你的业务场景必须能够表示成树形结构

享元模式

原理

享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象 不仅仅相同对象可以设计成享元,对于相似对象,我们也可以将这些对象中相同的部分(字段),提取出来设计成享元,在内存中只保留一份实例,供多处代码引用,这样可以减少内存中对象的数量,以起到节省内存的目的。前提是享元对象是不可变对象

实现

主要是通过工厂模式,在工厂类中,通过一个 Map 或者List 来缓存已经创建好的享元对象,以达到复用的目的

享元模式 VS 单例、缓存、对象池

应用单例模式是为了保证对象全局唯一 应用享元模式是为了实现对象复用,节省内存 缓存是为了提高访问效率,而非复用 池化技术中的“复用”理解为“重复使用”,主要是为了节省时间

享元模式在 Java Integer中的应用

如何判定两个 Java 对象是否相等 Java 对象在内存中的存储的是内存地址 通过“==”来判定两个对象是否相等的时候,实际上是在判断两个局部变量存储的地址是否相同,也就是在判断两个局部变量是否指向相同的对象 自动装箱(Autoboxing) Java 为基本数据类型提供了对应的包装器类型 自动将基本数据类型转换为包装器类型 自动拆箱(Unboxing):自动将包装器类型转化为基本数据类型 Integer 用到了享元模式来复用对象,当我们通过自动装箱,也就是调用 valueOf() 来创建 Integer 对象的时候,如果要创建的 Integer 对象的值在 -128 到 127 之间,会从 IntegerCache 类中直接返回,否则才调用 new 方法创建 IntegerCache 相当于生成享元对象的工厂类,在 IntegerCache 的代码实现中,当这个类被加载的时候,缓存的享元对象会被集中一次性创建好大部分应用来说最常用的整型值,也就是一个字节的大小(-128 到 127 之间的数 据) 三种创建整型对象的方式,优先使用后两种 Integer a = new Integer(123); Integer a = 123; Integer a = Integer.valueOf(123); 第一种创建方式并不会使用到 IntegerCache,而后面两种创建方法可以利用 IntegerCache 缓存,返回共享的对象,以达到节省内存的目的

享元模式在 String 中的应用

String 类利用享元模式来复用相同的字符串常量(也就是代码中的“小争哥”)。JVM 会专门开辟一块存储区来存储字符串常量,这块存储区叫作“字符串常量池”。 Integer 类中要共享的对 象,是在类加载的时候,就集中一次性创建好的。但是,对于字符串来说,我们没法事先知 道要共享哪些字符串常量,所以没办法事先创建好,只能在某个字符串常量第一次被用到的 时候,存储到常量池中,当之后再用到的时候,直接引用常量池中已经存在的即可,就不需 要再重新创建了

总结

代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能,这是它跟装饰器模式最大的不同

装饰者模式在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的嵌套使用

桥接模式的目的是将接口部分和实现部分分离,从而让它们可以较为容易、也相对独立地加以改变

适配器模式是一种事后的补救策略。适配器提供跟原始类不同的接口,而代理模式、装饰器模式提供的都是跟原始类相同的接口

门面模式为子系统提供一组统一的接口,定义一组高层接口让子系统更易用 使用组合模式的前提在于,你的业务场景必须能够表示成树形结构 享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值