java设计模式-享元模式

模式导读:

       世上没有相同的两片叶子,尽管它们可能非常相似,无论是颜色,大小亦或是重量等等,也会有不同之处,比如纹理,厚度等等。当我们需要将两片叶子用语言描述出来时,你是会选择两者分开描述,从颜色到厚度,从抽象到具体等等还是会选择两者同时描述,将共同点抽取出来然后细话两者不同。显然后者相比于前者既省时间又提高了辨识度,效率明显提升。享元模式在生活中随处可见,抽取相同属性放入一个容器以便共享,并且可以保证该属性不会随外部环境变化而发生变化。这便是享元模式。

核心:
享元模式以共享的方式高效的支持大量细粒度对象的重用。
享元对象能做到共享的关键是区分了内部状态和外部状态。
内部状态:可以共享,不会随环境变化而变化。
外部状态:不可以共享,会随环境变化而变化。
参考类图:

FlyweightFactory(享元工厂类):创建并管理享元对象,享元池一般设计成键值对。
FlyWeight(抽象享元类):通常是一个接口或抽象类,声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态。
ConcretFlyWeight(具体享元类):为内部状态提供成员变量进行存储。
UnsharedConcreteFlyWeight(非共享享元类):不能被共享的子类可以设计为非共享享元类。

代码实现:

1.抽象享元类

1 package com.etc;
2 //抽象享元类 ->内存卡
3 public interface AbstractMemoryCard {
4     //内存卡的颜色获取
5     String  getColor();
6     void setColor(String c);
7     void showMessage(ExternalState state);
8 }

2.具体享元类

 1 package com.etc;
 2 //具体的享元类
 3 public class MemoryCard implements AbstractMemoryCard {
 4 
 5     private String color;
 6     
 7     //构造器
 8     public MemoryCard(String color) {
 9         super();
10         this.color = color;
11     }
12 
13     @Override
14     public String getColor() {
15         return color;
16     }
17 
18     @Override
19     public void setColor(String color) {
20         this.color=color;
21     }
22 
23     @Override
24     public void showMessage(ExternalState state) {
25         System.out.println("******内存卡信息:*******");
26         System.out.println("*颜色:"+color);
27         System.out.println("*品牌:"+state.getBrand());
28         System.out.println("*内存大小:"+state.getStoreSize()+"g");
29         System.out.println("*********************");
30     }
31 
32 }

3.非共享享元类

 1 package com.etc;
 2 //非共享享元类(外部状态类)->包含内存卡的内存大小,以及相应的品牌
 3 public class ExternalState {
 4     
 5     private int storeSize;
 6     private String brand;
 7     
 8     public ExternalState(int storeSize, String brand) {
 9         super();
10         this.storeSize = storeSize;
11         this.brand = brand;
12     }
13     public int getStoreSize() {
14         return storeSize;
15     }
16     public void setStoreSize(int storeSize) {
17         this.storeSize = storeSize;
18     }
19     public String getBrand() {
20         return brand;
21     }
22     public void setBrand(String brand) {
23         this.brand = brand;
24     }
25     
26 
27 }

4.享元工厂

 1 package com.etc;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 //享元工厂类
 7 public class Factory {
 8     //建立享元池
 9     private static Map<String,AbstractMemoryCard> map=new HashMap<String,AbstractMemoryCard>();
10     //通过内存卡的共同属性color返回对象地址
11     public static AbstractMemoryCard getMemoryCard(String color) {
12         //如果获取的color不为空直接返回color
13         if(map.get(color)!=null) {
14             return map.get(color);
15         }else {
16             //为空则初始化color并将其放入享元池中
17             AbstractMemoryCard amc=new MemoryCard(color);
18             map.put(color, amc);
19             return amc;
20         }
21     }
22     
23 }

5.客户端

 1 package com.etc;
 2 
 3 public class Client {
 4 
 5     public static void main(String[] args) {
 6         
 7         //因为color属性为共享属性,所以在此已经初始化了color的值为黑色
 8         AbstractMemoryCard amc=Factory.getMemoryCard("黑色");
 9         //color的值已经存在,所以返回相同的对象
10         AbstractMemoryCard amc2=Factory.getMemoryCard("黑色");
11         System.out.println(amc==amc2?"两个对象相同":"两个对象不相同");
12         
13         ExternalState state=new ExternalState(16,"三星");
14         ExternalState state2=new ExternalState(32,"闪迪");
15         //信息展示
16         amc.showMessage(state);
17         amc2.showMessage(state2);
18     }
19 
20 }

效果截图:

享元模式优缺点:

优点:

1.极大的减少了内存中对象的数量

2.相同或相似的对象在内存中只占一份,极大的节约资源,提高了系统性能。

3.外部状态相对独立,不会影响内部状态。

缺点:

1.模式较复杂,使程序逻辑复杂化

2.为了节省内存,共享了内部状态,分离出外部状态,而读取外部状态使运行时间变长,用时间换取了空间。

适用场景:

1.可以在任何"池"中操作,比如线程池,数据库连接池。

2.String类的设计也是享元模式

原文地址:https://www.cnblogs.com/weekstart/p/10880135.html