首页 > 其他分享 >设计模式--结构型模式

设计模式--结构型模式

时间:2022-11-21 12:00:59浏览次数:75  
标签:享元 -- 适配器 代理 接口 对象 模式 设计模式 结构型

设计模式--结构型模式

结构型模式,共七种:

适配器模式(新接口用老实现类)、装饰器模式(同代理,增强)、代理模式(方法前后)、外观模式(计算机包括…)、桥接模式(中间表)、组合模式(树)、享元模式(共享池)。

1. 适配器模式(Adapter Pattern)

代理模式、装饰器模式提供的都是跟原始类相同的接口,而适配器提供跟原始类不同的接口。别名叫:Wrapper(包装器)

适配器模式是用来做适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。适配器模式有两种实现方式:类适配器和对象适配器。其中,类适配器使用继承关系来实现,对象适配器使用组合关系来实现。

适配器模式是一种事后的补救策略,用来补救设计上的缺陷。应用这种模式算是“无奈之举”。如果在设计初期,我们就能规避接口不兼容的问题,那这种模式就无用武之地了。在实际的开发中,什么情况下才会出现接口不兼容呢?我总结下了下面这5种场景:

  1. 封装有缺陷的接口设计
  2. 统一多个类的接口设计
  3. 替换依赖的外部系统
  4. 兼容老版本接口
  5. 适配不同格式的数据

举例:
1.

实现:
Adapter 适配器,把 Adeptee 适配成 Target。
Adaptee 被适配的内容,比如不兼容的接口。
Target 适配为的内容,比如需要用的接口。
适配器继承 Adaptee 并实现 Target,适用场景是 Adaptee 与 Target 结构类似的情况,因为这样只需要实现部分差异化即可。

参考
https://zhuanlan.zhihu.com/p/369272002 代码

2. 装饰器模式

装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承,给原始类添加增强功能。这也是判断是否该用装饰器模式的一个重要的依据。除此之外,装饰器模式还有一个特点,那就是可以对原始类嵌套使用多个装饰器。为了满足这样的需求,在设计的时候,装饰器类需要跟原始类继承相同的抽象类或者接口。

装饰者模式的精髓在于动态的给对象增减功能。

public static void main(String[] args) {
        //原味咖啡
        ICoffee coffee=new OriginalCoffee();
        coffee.makeCoffee();
        System.out.println("");

        //加奶的咖啡
        coffee=new MilkDecorator(coffee);
        coffee.makeCoffee();
        System.out.println("");

        //先加奶后加糖的咖啡
        coffee=new SugarDecorator(coffee);
        coffee.makeCoffee();
    }

装饰者模式与代理模式的区别

一般认为代理模式侧重于使用代理类增强被代理对象的访问,而装饰者模式侧重于使用装饰者类来对被装饰对象的功能进行增强。 除了上面的区别,个人实践中还发现,装饰者模式主要是提供一组装饰者类,然后形成一个装饰者栈,来动态的对某一个对象不断加强,而代理一般不会使用多级代理,详情请见

https://zhuanlan.zhihu.com/p/64584677 代码

3. 代理模式

代理模式(方法前后)

代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能,这是它跟装饰器模式最大的不同。一般情况下,我们让代理类和原始类实现同样的接口。但是,如果原始类并没有定义接口,并且原始类代码并不是我们开发维护的。在这种情况下,我们可以通过让代理类继承原始类的方法来实现代理模式。

静态代理需要针对每个类都创建一个代理类,并且每个代理类中的代码都有点像模板式的“重复”代码,增加了维护成本和开发成本。对于静态代理存在的问题,我们可以通过动态代理来解决。我们不事先为每个原始类编写代理类,而是在运行的时候动态地创建原始类对应的代理类,然后在系统中用代理类替换掉原始类。

代理模式常用在业务系统中开发一些非功能性需求,比如:监控、统计、鉴权、限流、事务、幂等、日志。我们将这些附加功能与业务功能解耦,放到代理类统一处理,让程序员只需要关注业务方面的开发。除此之外,代理模式还可以用在RPC、缓存等应用场景中。

JDK动态代理实现的原理

  1. 首先Jdk的动态代理实现方法是依赖于接口的,首先使用接口来定义好操作的规范。然后通过Proxy类产生的代理对象调用被代理对象的操作,而这个操作又被分发给InvocationHandler接口的 invoke方法具体执行

cgLib的动态代理实现

  1. 由于JDK只能针对实现了接口的类做动态代理,而不能对没有实现接口的类做动态代理,所以cgLib横空出世!CGLib(Code Generation Library)是一个强大、高性能的Code生成类库,它可以在程序运行期间动态扩展类或接口,它的底层是使用java字节码操作框架ASM实现。
  2. CGLIB原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。
  3. CGLIB底层:使用字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
  4. CGLIB缺点:对于final方法,无法进行代理。

参考
https://zhuanlan.zhihu.com/p/58092627 代码
https://blog.csdn.net/shusheng0007/article/details/80864854

4. 外观模式

外观模式(计算机包括…)

门面模式原理、实现都非常简单,应用场景比较明确。它通过封装细粒度的接口,提供组合各个细粒度接口的高层次接口,来提高接口的易用性,或者解决性能、分布式事务等问题。

使用场景
当你的程序有很多个模块,或者说子系统。你希望给用户提供一个统一的操作界面类,而不是让用户分别与这些模块交互。

参考
https://zhuanlan.zhihu.com/p/370031071

5. 桥接模式

桥接模式(中间表)

讲抽象部分和实现部分, 进一步分割开。

6. 组合模式(Composite Pattern)

组合模式(树)

组合模式跟我们之前讲的面向对象设计中的“组合关系(通过组合来组装两个类)”,完全是两码事。这里讲的“组合模式”,主要是用来处理树形结构数据。正因为其应用场景的特殊性,数据必须能表示成树形结构,这也导致了这种模式在实际的项目开发中并不那么常用。但是,一旦数据满足树形结构,应用这种模式就能发挥很大的作用,能让代码变得非常简洁。

组合模式的设计思路,与其说是一种设计模式,倒不如说是对业务场景的一种数据结构和算法的抽象。其中,数据可以表示成树这种数据结构,业务需求可以通过在树上的递归遍历算法来实现。组合模式,将一组对象组织成树形结构,将单个对象和组合对象都看作树中的节点,以统一处理逻辑,并且它利用树形结构的特点,递归地处理每个子树,依次简化代码实现。

使用场景:

  1. 当你的程序结构有类似树一样的层级关系时,例如文件系统,视图树,公司组织架构等等
  2. 当你要以统一的方式操作单个对象和由这些对象组成的组合对象的时候。

参考:
https://zhuanlan.zhihu.com/p/369731677

7. 享元模式(Flyweight Pattern)

享元模式(共享池),真是扯淡的中文翻译,英文为(Flyweight Pattern),直译是轻量模式,通过一系列的共享对象方式、减少对象创建、降低内存使用。

整理下模式框架代码

  1. 抽象享元(Flyweight)角色 :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。
  2. 具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。
  3. 享元工厂(FlyweightFactory)角色 :本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象。

参考:

  1. https://www.cnblogs.com/draem0507/p/3793243.html

标签:享元,--,适配器,代理,接口,对象,模式,设计模式,结构型
From: https://www.cnblogs.com/starmoon1994/p/16881000.html

相关文章

  • eclipse报错:The method convert(String) of type DateConvertor must override a supe
    ​​@Overridemustoverrideasuperclassmethod问题解决​​如果在使用Eclipse开发Java项目时,在使用@Override出现以下错误:Themethod***oftype***mustoverr......
  • 如何取消电脑系统自动更新
    在上网的时候,经常会提示有更新,这样对电脑配置不高的电脑来说是一个不小的负担,会影响电脑的使用速度,那么如何取消电脑系统自动更新呢?系统更新SystemUpdate如何取消电脑......
  • Can not find the tag library descriptor for
    Cannotfindthetaglibrarydescriptorfor"http://java.sun.com/jsp/jstl/有时候,web工程会报错,错误提示为:Cannotfindthetaglibrarydescriptorfor"http://​......
  • 17.3 给内存映射文件指定基地址--《Windows核心编程》
    可以使用MapViewOfFileEx函数,建议系统把文件映射到指定的地址。其他参数与MapViewOfFile相同,最后一个参数pvBaseeAddress指定目标地址。同VirtualAlloc,指定的地址......
  • Python psutil模块 Process 类
    psutil模块Process类如果需要了解其他跟多理解的=》Python知识点合集 如果需要查看官方手册解读的=》Process类......
  • 设计模式--行为型模式
    设计模式--行为型模式行为型模式,共十一种:策略模式(Calculator子类)、模板方法模式(大象装冰箱)、观察者模式(观察者列表)、迭代子模式、责任链模式、命令模式(一层接一层)、备忘......
  • IntelliJ IDEA详细安装步骤
    IntelliJIDEA详细安装步骤一、安装IntelliJIDEA1运行IntelliJIDEA安装程序 2同意协议 3选择安装路径,比如D:\ProgramFiles(x86)\JetBrains\IntelliJIDEA14.0.1......
  • 微信小程序创建文件,点击尝试
    设置需要关闭代理容器组件-view的使用做布局app.json中直接创建文件:容器组件html标签无法解析:不认识标签,没写创建文件:pages/second/secondview类似(html的div)......
  • springboot配置多数据源
    最近在做一个换电站的项目需要用到多数据源,配置方法如下一:在yml文件里先把数据源信息配置好spring:application:name:base-serverdatasource:type:co......
  • Unity Shader 4 ShaderLab
    通用基础的ShaderUnlit不发光的纹理VertexLit顶点光照Diffuse漫反射Normalmapped法线贴图,增加一个或更多纹理和几个着色器结构Specular镜面高光,模拟......