设计模式——结构型模式简单介绍

结构型模式

结构型模式旨在通过改变代码结构来达到解耦的目的,使得我们的代码容易维护和扩展。

代理模式

代理,那就要对客户端隐藏真实实现,由代理来负责客户端的所有请求。

用一个代理来隐藏具体实现类的实现细节,通常还用于在真实的实现的前后添加一部分逻辑。

proxy

类似一个接口,接口的实现类(代理)

Spring中的动态代理有两种:

  1. 如果我们的类定义了接口,如 UserService 接口和 UserServiceImpl 实现,那么采用 JDK 的动态代理,感兴趣的读者可以去看看 java.lang.reflect.Proxy 类的源码;
  2. 我们自己没有定义接口的,Spring 会采用 CGLIB 进行动态代理,它是一个 jar 包,性能还不错。

适配器模式

适配器模式做的就是,有一个接口需要实现,但是我们现成的对象都不满足,需要加一层适配器来进行适配。

适配器模式总体来说分三种:默认适配器模式、对象适配器模式、类适配器模式。先不急着分清楚这几个,先看看例子再说。

默认适配器模式

如我们需要实现接口,但是不想实现接口的所有类。

那么用一个实现接口类(适配器)实现那些接口,但是所有的方法都是空方法(类似于方法{}),然后其他类继承这个类即可。

对象适配器模式

在这里插入图片描述

鸡需要用到鸭的方法。

(组合)用鸡适配器实现鸭的方法,并注入鸡。

鸡适配器需要做到

  1. 注入进来**(组合)**
  2. 实现并重写鸭的接口

客户端调用,创建鸡->(通过鸡注入)来创建鸡适配器。

类适配器模式

adapter-1

类适配器同样是鸡要用鸭的方法。

(继承)鸡适配器继承鸡又实现鸭。一气呵成。

通过继承的方法,适配器自动获得了所需要的大部分方法。这个时候,客户端使用更加简单,直接 Target t = new SomeAdapter(); 就可以了。

适配器模式总结

对象适配和类适配的异同
  • 对象适配(组合),类适配(继承)
  • 对象适配(组合动态实现)需要在适配器里实例化对象,类适配(静态实现)。
  • 对象适配比类适配用的多。
代理模式和适配器(对象适配器)模式的异同

比较代理模式和对象适配器模式。

同:在代码结构上,它们很相似,都需要一个具体的实现类的实例

异:目的不同

代理模式是增强原方法。

适配器做的是适配的活,为的是提供“把鸡包装成鸭,然后当做鸭来使用”。

adapter-5

桥梁模式

bridge-1

理解桥梁模式,其实就是理解代码抽象和解耦。

我们首先需要一个桥梁,它是一个接口,定义提供的接口方法。

然后是一系列实现类。

在这里插入图片描述

接口(桥梁):实现接口类

抽象类注入接口):抽象类的实现类

装饰模式

Java IO 中的几个类是典型的装饰模式的应用

首先,我们先看一个简单的图,看这个图的时候,了解下层次结构就可以了:

decorator-1

decorator-2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vG1IYtwc-1629789076947)(C:\Users\w2022\AppData\Roaming\Typora\typora-user-images\image-20210824142414112.png)]

客户端调用:

public static void main(String[] args) {
    // 首先,我们需要一个基础饮料,红茶、绿茶或咖啡
    Beverage beverage = new GreenTea();
    // 开始装饰
    beverage = new Lemon(beverage); // 先加一份柠檬
    beverage = new Mongo(beverage); // 再加一份芒果

    System.out.println(beverage.getDescription() + " 价格:¥" + beverage.cost());
    //"绿茶, 加柠檬, 加芒果 价格:¥16"
}

如果我们需要 芒果-珍珠-双份柠檬-红茶

Beverage beverage = new Mongo(new Pearl(new Lemon(new Lemon(new BlackTea()))));

java IO 中的装饰模式。看下图 InputStream 派生出来的部分类:

decorator-3

InputStream 代表了输入流,具体的输入来源有

  • 文件(FileInputStream)
  • 管道(PipedInputStream)
  • 数组(ByteArrayInputStream)等。

FilterInputStream 承接了装饰模式的关键节点,它的实现类是一系列装饰器,比如

  • BufferedInputStream: 代表用缓冲来装饰,也就使得输入流具有了缓冲的功能
  • LineNumberInputStream: 代表用行号来装饰,在操作的时候就可以取得行号
  • DataInputStream 的装饰:从输入流转换为 java 中的基本类型值

当然,在 java IO 中,如果我们使用装饰器的话,就不太适合面向接口编程了,如:

InputStream inputStream = new LineNumberInputStream(new BufferedInputStream(new FileInputStream("")));

这样的结果是,InputStream 还是不具有读取行号的功能,因为读取行号的方法定义在 LineNumberInputStream 类中。

我们应该像下面这样使用:

LineNumberInputStream is = new LineNumberInputStream(
                              new BufferedInputStream(
                                  new FileInputStream("")));

外观模式/门面模式(Facade Pattern)

门面模式(也叫外观模式,Facade Pattern)在许多源码中有使用,比如 slf4j 就可以理解为是门面模式的应用。这是一个简单的设计模式。

一个门面,在门面里面实例化每个类,里面的方法分别调用实例化对象引用的方法。

门面部分:

public class ShapeMaker {
   private Shape circle;
   private Shape rectangle;
   private Shape square;

   public ShapeMaker() {
      circle = new Circle();
      rectangle = new Rectangle();
      square = new Square();
   }

  /**
   * 下面定义一堆方法,具体应该调用什么方法,由这个门面来决定
   */

   public void drawCircle(){
      circle.draw();
   }
   public void drawRectangle(){
      rectangle.draw();
   }
   public void drawSquare(){
      square.draw();
   }
}

组合模式

组合模式用于表示具有层次结构的数据,使得我们对单个对象和组合对象的访问具有一致性。

类似某个类里面的成员还有个List?

定义 add(node)、remove(node)、getChildren() 这些方法的基本都是组合模式。

享元模式

享元分开来说就是 共享 元器件,也就是复用已经生成的对象,这种做法当然也就是轻量级的了。

复用对象最简单的方式是,用一个 HashMap 来存放每次新生成的对象每次需要一个对象的时候,先到 HashMap 中看看有没有,如果没有,再生成新的对象,然后将这个对象放入 HashMap 中

结构型模式总结

代理模式方法增强

适配器模式:把鸡包装成鸭这种用来适配接口的

桥梁模式:做到了很好的解耦

装饰模式:适合于装饰类或者说是增强类的场景

门面模式的优点是客户端不需要关心实例化过程,只要调用需要的方法即可

组合模式用于描述具有层次结构的数据

享元模式是为了在特定的场景中缓存已经创建的对象,用于提高性能。

引用:设计模式也可以这么简单

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值