享元模式

享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。

享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

假设一个场景:有一盘围棋,有黑白二色旗子,对于任意一方来说,每一个棋子长得都是一样的,但是我们需要用位置来区分每个棋子。如果我们为每一个棋子创建一个对象,显然会创建大量的对象,这增加了大量的小对象,造成了对象管理的困难。所以我们引入了享元模式,把棋子共有的颜色等属性抽象出来,把棋子不共有的,如位置等,另外构成一个类。

FlyWeight接口

 1 package top.bigking.flyWeight;
 2 
 3 /**
 4  * @Author ABKing
 5  * @since 2020/2/25 下午10:12
 6  **/
 7 public interface FlyWeight {
 8     void getColor();
 9     void getPosition(UnsharedConcreteFlyWeight position);
10 }

FlyWeight的实现类,ConcreteFlyWeight类,增加了内部状态(共有的)

 1 package top.bigking.flyWeight;
 2 
 3 /**
 4  * @Author ABKing
 5  * @since 2020/2/25 下午10:13
 6  * 内部状态 ConcreteFlyWeight
 7  **/
 8 public class ConcreteFlyWeight implements FlyWeight {
 9     private String color;
10 
11     public ConcreteFlyWeight(String color) {
12         this.color = color;
13     }
14 
15     @Override
16     public void getColor() {
17         System.out.println("颜色是: " + color);
18     }
19 
20     @Override
21     public void getPosition(UnsharedConcreteFlyWeight position) {
22         System.out.println("位置是: " + position);
23     }
24 
25 
26 }

外部状态,UnsharedConcreteFlyWeight类

 1 package top.bigking.flyWeight;
 2 
 3 /**
 4  * @Author ABKing
 5  * @since 2020/2/25 下午10:14
 6  * 外部状态 UnsharedConcreteFlyWeight
 7  **/
 8 public class UnsharedConcreteFlyWeight {
 9     private String x, y;
10 
11     public UnsharedConcreteFlyWeight(String x, String y) {
12         this.x = x;
13         this.y = y;
14     }
15 
16     @Override
17     public String toString() {
18         return "x是" + x + ", y是" + y;
19     }
20 
21     public String getX() {
22         return x;
23     }
24 
25     public void setX(String x) {
26         this.x = x;
27     }
28 
29     public String getY() {
30         return y;
31     }
32 
33     public void setY(String y) {
34         this.y = y;
35     }
36 }

享元模式通常与工厂模式结合起来使用,写一个FlyWeightFactory类

 1 package top.bigking.flyWeight;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 /**
 7  * @Author ABKing
 8  * @since 2020/2/25 下午10:34
 9  **/
10 public class FlyWeightFactory {
11     //享元池
12     private static Map<String, FlyWeight> map = new HashMap<>();
13 
14     public static FlyWeight getFlyWeight(String color){
15         FlyWeight flyWeight = map.get(color);
16         if(flyWeight != null){//池中有对象
17             return flyWeight;
18         }else {//池中无对象
19             FlyWeight fw = new ConcreteFlyWeight(color);
20             map.put(color, fw);
21             return fw;
22         }
23     }
24 }

JUnit单元测试:

 1 package top.bigking.flyWeight;
 2 
 3 import org.junit.Test;
 4 
 5 /**
 6  * @Author ABKing
 7  * @since 2020/2/25 下午10:40
 8  **/
 9 public class TestFlyWeight {
10     @Test
11     public void testFlyWeight(){
12         FlyWeight flyWeight = FlyWeightFactory.getFlyWeight("黑色");
13         FlyWeight flyWeight2 = FlyWeightFactory.getFlyWeight("黑色");
14         System.out.println(flyWeight == flyWeight2);
15         flyWeight.getColor();
16         flyWeight2.getColor();
17         flyWeight.getPosition(new UnsharedConcreteFlyWeight("10", "15"));
18         flyWeight2.getPosition(new UnsharedConcreteFlyWeight("20", "20"));
19     }
20 }

优点:

  • 极大减少内存中对象的数量
  • 相同或相似对象内存中只存一份,极大地节约资源,提高系统性能。
  • 外部状态相对独立,不影响内部状态。

缺点:

  • 模式较复杂,使程序逻辑复杂化
  • 为了节省内存,共享了内部状态,分理出外部状态,而读取外部状态使运行时间边长。用时间换取了空间。
  • 由于是共享同一个对象,所以后一个改变外部状态会影响前一个的外部状态。

享元模式开发应用中的场景:

享元模式由于其共享的特性,可以在任何池中操作,比如:线程池,数据库连接池

String类的设计也是享元模式

金麟岂是池中物,一遇风云便化龙!
原文地址:https://www.cnblogs.com/ABKing/p/12363807.html