彻底搞懂设计模式DesignPattern-享元模式

本文已参与「新人创作礼」活动,一起开启掘金创作之路

享元模式的原理

《大话设计模式》中这样定义享元模式:运用共享技术有效的支持大量细粒度的对象。 问题1:共享技术是指什么?细粒度的对象是什么? 共享技术是一种通过共享池避免重复生成大量的相似对象的技术。 细粒度的对象是指实现一个接口的类的对象,使用过程中会大量产生的对象,对象之间有大量重复的不可变的信息(类型),只有少量可变的信息(位置)。 问题2:如何支持(实现)细粒度的对象共享? 在享元模式中,把对象内部不可变的信息(如类型)称为内部状态,把少量可变的信息(如位置)提取到对象外部,如客户端来决定可变信息,这种可变信息称为外部状态。所以,共享是根据内部状态把对象放入共享池内,客户端传入外部状态和内部状态来获取共享池内的对象。 享元模式的UML类图: 在这里插入图片描述

享元模式各角色介绍:

Flyweight:所有具体享元类的抽象类或者接口,通过这个接口,Flyweight可以接受并作用于外部状态。 ConcreteFlyweight:继承Flyweight抽象类或者接口,并为内部状态增加存储空间; UnsharedConcreteFlyweight:继承Flyweight抽象类或者接口,指那些不需要共享的Flyweight子类。因为Flyweight接口共享成为可能,但他并不强制共享。 FlyweightFactory:一个享元工厂,用来创建并管理Flyweight对象,它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。

内部状态和外部状态

比如围棋、五子棋、跳棋,它们都有大量的棋子对象,围棋和五子棋只有黑白两色,跳棋颜色多一点,所以棋子颜色就是棋子的内部状态;而各个棋子之间的差别就是位置的不同,当我们落子后, 落子颜色是定的,但位置是变化的,所以棋子坐标就是棋子的外部状态

  1. 享元模式提出了两个要求:细粒度和共享对象。这里就涉及到内部状态和外部状态了,即将对象的信息分为两个部分: 内部状态和外部状态
  2. 内部状态指对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变
  3. 外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态。
  4. 举个例子:围棋理论上有361个空位可以放棋子,每盘棋都有可能有两三百个棋子对

象产生,因为内存空间有限,一台服务器很难支持更多的玩家玩围棋游戏,如果用享元模式来处理棋子,那么棋子对象就可以减少到只有两个实例,这样就很好的解决了对象的开销问题。

享元模式的特点

避免重复创建对象,节省内存空间。根据内部状态把对象存储在共享池,需要时去共享池取就行。

享元模式使用场景

借用设计模式书中的话就是:如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。

享元模式的注意事项和细节

  1. 在享元模式这样理解,“享”就表示共享,“元”表示对象
  2. 系统中有大量对象, 这些对象消耗大量内存, 并且对象的状态大部分可以外部化时,我们就可以考虑选用享元模式
  3. 用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象,用HashMap/HashTable存储
  4. 享元模式大大减少了对象的创建,降低了程序内存的占用,提高效率
  5. 享元模式提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变,这是我们使用享元模式需要注意的地方.
  6. 使用享元模式时,注意划分内部状态和外部状态,并且需要有一个工厂类加以控制。
  7. 享元模式经典的应用场景是需要缓冲池的场景,比如 String常量池、 数据库连接池

代码示例

码云地址https://gitee.com/magneto/codeReview/tree/master/DesignPattern/src/pro51/top

享元模式的原理

《大话设计模式》中这样定义享元模式:运用共享技术有效的支持大量细粒度的对象。 问题1:共享技术是指什么?细粒度的对象是什么? 共享技术是一种通过共享池避免重复生成大量的相似对象的技术。 细粒度的对象是指实现一个接口的类的对象,使用过程中会大量产生的对象,对象之间有大量重复的不可变的信息(类型),只有少量可变的信息(位置)。 问题2:如何支持(实现)细粒度的对象共享? 在享元模式中,把对象内部不可变的信息(如类型)称为内部状态,把少量可变的信息(如位置)提取到对象外部,如客户端来决定可变信息,这种可变信息称为外部状态。所以,共享是根据内部状态把对象放入共享池内,客户端传入外部状态和内部状态来获取共享池内的对象。 享元模式的UML类图: 在这里插入图片描述

享元模式各角色介绍:

Flyweight:所有具体享元类的抽象类或者接口,通过这个接口,Flyweight可以接受并作用于外部状态。 ConcreteFlyweight:继承Flyweight抽象类或者接口,并为内部状态增加存储空间; UnsharedConcreteFlyweight:继承Flyweight抽象类或者接口,指那些不需要共享的Flyweight子类。因为Flyweight接口共享成为可能,但他并不强制共享。 FlyweightFactory:一个享元工厂,用来创建并管理Flyweight对象,它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。

内部状态和外部状态

比如围棋、五子棋、跳棋,它们都有大量的棋子对象,围棋和五子棋只有黑白两色,跳棋颜色多一点,所以棋子颜色就是棋子的内部状态;而各个棋子之间的差别就是位置的不同,当我们落子后, 落子颜色是定的,但位置是变化的,所以棋子坐标就是棋子的外部状态

  1. 享元模式提出了两个要求:细粒度和共享对象。这里就涉及到内部状态和外部状态了,即将对象的信息分为两个部分: 内部状态和外部状态
  2. 内部状态指对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变
  3. 外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态。
  4. 举个例子:围棋理论上有361个空位可以放棋子,每盘棋都有可能有两三百个棋子对

象产生,因为内存空间有限,一台服务器很难支持更多的玩家玩围棋游戏,如果用享元模式来处理棋子,那么棋子对象就可以减少到只有两个实例,这样就很好的解决了对象的开销问题。

享元模式的特点

避免重复创建对象,节省内存空间。根据内部状态把对象存储在共享池,需要时去共享池取就行。

享元模式使用场景

借用设计模式书中的话就是:如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。

享元模式的注意事项和细节

  1. 在享元模式这样理解,“享”就表示共享,“元”表示对象
  2. 系统中有大量对象, 这些对象消耗大量内存, 并且对象的状态大部分可以外部化时,我们就可以考虑选用享元模式
  3. 用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象,用HashMap/HashTable存储
  4. 享元模式大大减少了对象的创建,降低了程序内存的占用,提高效率
  5. 享元模式提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变,这是我们使用享元模式需要注意的地方.
  6. 使用享元模式时,注意划分内部状态和外部状态,并且需要有一个工厂类加以控制。
  7. 享元模式经典的应用场景是需要缓冲池的场景,比如 String常量池、 数据库连接池

享元模式的原理

《大话设计模式》中这样定义享元模式:运用共享技术有效的支持大量细粒度的对象。 问题1:共享技术是指什么?细粒度的对象是什么? 共享技术是一种通过共享池避免重复生成大量的相似对象的技术。 细粒度的对象是指实现一个接口的类的对象,使用过程中会大量产生的对象,对象之间有大量重复的不可变的信息(类型),只有少量可变的信息(位置)。 问题2:如何支持(实现)细粒度的对象共享? 在享元模式中,把对象内部不可变的信息(如类型)称为内部状态,把少量可变的信息(如位置)提取到对象外部,如客户端来决定可变信息,这种可变信息称为外部状态。所以,共享是根据内部状态把对象放入共享池内,客户端传入外部状态和内部状态来获取共享池内的对象。 享元模式的UML类图: 在这里插入图片描述

享元模式各角色介绍:

Flyweight:所有具体享元类的抽象类或者接口,通过这个接口,Flyweight可以接受并作用于外部状态。 ConcreteFlyweight:继承Flyweight抽象类或者接口,并为内部状态增加存储空间; UnsharedConcreteFlyweight:继承Flyweight抽象类或者接口,指那些不需要共享的Flyweight子类。因为Flyweight接口共享成为可能,但他并不强制共享。 FlyweightFactory:一个享元工厂,用来创建并管理Flyweight对象,它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。

内部状态和外部状态

比如围棋、五子棋、跳棋,它们都有大量的棋子对象,围棋和五子棋只有黑白两色,跳棋颜色多一点,所以棋子颜色就是棋子的内部状态;而各个棋子之间的差别就是位置的不同,当我们落子后, 落子颜色是定的,但位置是变化的,所以棋子坐标就是棋子的外部状态

  1. 享元模式提出了两个要求:细粒度和共享对象。这里就涉及到内部状态和外部状态了,即将对象的信息分为两个部分: 内部状态和外部状态
  2. 内部状态指对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变
  3. 外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态。
  4. 举个例子:围棋理论上有361个空位可以放棋子,每盘棋都有可能有两三百个棋子对

象产生,因为内存空间有限,一台服务器很难支持更多的玩家玩围棋游戏,如果用享元模式来处理棋子,那么棋子对象就可以减少到只有两个实例,这样就很好的解决了对象的开销问题。

享元模式的特点

避免重复创建对象,节省内存空间。根据内部状态把对象存储在共享池,需要时去共享池取就行。

享元模式使用场景

借用设计模式书中的话就是:如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。

享元模式的注意事项和细节

  1. 在享元模式这样理解,“享”就表示共享,“元”表示对象
  2. 系统中有大量对象, 这些对象消耗大量内存, 并且对象的状态大部分可以外部化时,我们就可以考虑选用享元模式
  3. 用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象,用HashMap/HashTable存储
  4. 享元模式大大减少了对象的创建,降低了程序内存的占用,提高效率
  5. 享元模式提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变,这是我们使用享元模式需要注意的地方.
  6. 使用享元模式时,注意划分内部状态和外部状态,并且需要有一个工厂类加以控制。
  7. 享元模式经典的应用场景是需要缓冲池的场景,比如 String常量池、 数据库连接池

享元模式的原理

《大话设计模式》中这样定义享元模式:运用共享技术有效的支持大量细粒度的对象。 问题1:共享技术是指什么?细粒度的对象是什么? 共享技术是一种通过共享池避免重复生成大量的相似对象的技术。 细粒度的对象是指实现一个接口的类的对象,使用过程中会大量产生的对象,对象之间有大量重复的不可变的信息(类型),只有少量可变的信息(位置)。 问题2:如何支持(实现)细粒度的对象共享? 在享元模式中,把对象内部不可变的信息(如类型)称为内部状态,把少量可变的信息(如位置)提取到对象外部,如客户端来决定可变信息,这种可变信息称为外部状态。所以,共享是根据内部状态把对象放入共享池内,客户端传入外部状态和内部状态来获取共享池内的对象。 享元模式的UML类图: 在这里插入图片描述

享元模式各角色介绍:

Flyweight:所有具体享元类的抽象类或者接口,通过这个接口,Flyweight可以接受并作用于外部状态。 ConcreteFlyweight:继承Flyweight抽象类或者接口,并为内部状态增加存储空间; UnsharedConcreteFlyweight:继承Flyweight抽象类或者接口,指那些不需要共享的Flyweight子类。因为Flyweight接口共享成为可能,但他并不强制共享。 FlyweightFactory:一个享元工厂,用来创建并管理Flyweight对象,它主要是用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)。

内部状态和外部状态

比如围棋、五子棋、跳棋,它们都有大量的棋子对象,围棋和五子棋只有黑白两色,跳棋颜色多一点,所以棋子颜色就是棋子的内部状态;而各个棋子之间的差别就是位置的不同,当我们落子后, 落子颜色是定的,但位置是变化的,所以棋子坐标就是棋子的外部状态

  1. 享元模式提出了两个要求:细粒度和共享对象。这里就涉及到内部状态和外部状态了,即将对象的信息分为两个部分: 内部状态和外部状态
  2. 内部状态指对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变
  3. 外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态。
  4. 举个例子:围棋理论上有361个空位可以放棋子,每盘棋都有可能有两三百个棋子对

象产生,因为内存空间有限,一台服务器很难支持更多的玩家玩围棋游戏,如果用享元模式来处理棋子,那么棋子对象就可以减少到只有两个实例,这样就很好的解决了对象的开销问题。

享元模式的特点

避免重复创建对象,节省内存空间。根据内部状态把对象存储在共享池,需要时去共享池取就行。

享元模式使用场景

借用设计模式书中的话就是:如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。

享元模式的注意事项和细节

  1. 在享元模式这样理解,“享”就表示共享,“元”表示对象
  2. 系统中有大量对象, 这些对象消耗大量内存, 并且对象的状态大部分可以外部化时,我们就可以考虑选用享元模式
  3. 用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象,用HashMap/HashTable存储
  4. 享元模式大大减少了对象的创建,降低了程序内存的占用,提高效率
  5. 享元模式提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变,这是我们使用享元模式需要注意的地方.
  6. 使用享元模式时,注意划分内部状态和外部状态,并且需要有一个工厂类加以控制。
  7. 享元模式经典的应用场景是需要缓冲池的场景,比如 String常量池、 数据库连接池

猜你喜欢

转载自juejin.im/post/7088505397639643173