博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java设计模式--享元模式
阅读量:6276 次
发布时间:2019-06-22

本文共 4745 字,大约阅读时间需要 15 分钟。

享元模式

运用共享技术有效的支持大量细粒度的对象。

Flyweight Pattern

Use sharing to support large numbers of fine-grained objects efficiently.

类图

模式的结构与使用

享元方法模式的结构中包括三种角色。

+ 享元接口(Flyweight):是一个接口,该接口定义了享元对外公开其内部数据的方法,以及享元接收外部数据的方法。
+ 具体享元(Concrete Flyweight):实现享元接口的类,该类的实例称为享元对象,或简称享元。具体享元类的成员变量为享元对象的内部状态,享元对象的内部状态必须与所处的周围环境无关,即要保证使用享元对象的应用程序无法更改享元的内部状态,只有这样才能使得享元对象在系统中被共享。因为享元对象是用来共享的,所以不能允许用户各自地使用具体享元类来创建对象,这样就无法达到共享的目的,因为不同用户用具体享元类创建的对象显然是不同的,所以,具体享元类的构造方法必须是private的,其目的是不允许用户程序直接使用具体享元类来创建享元对象,创建和管理享元对象由享元工厂负责。
+ 享元工厂(Flyweight Factory):享元工厂是一个类,该类的实例负责创建和管理享元对象,用户或其他对象必须请求享元工厂为它得到一个享元对象。享元工厂可以通过一个散列表(也称共享池)来管理享元对象,当用户程序或其他若干个对象向享元工厂请求一个享元对象时,如果享元工厂的散列表中已有这样的享元对象,享元工厂就提供这个享元对象给请求者,否则就创建一个享元对象添加到散列表中,同时该享元对象提供给请求者。显然,当若干个用户或对象请求享元工厂提供一个享元对象时,第一个用户获得该享元对象的时间可能慢一些,但是后继的用户会较快地获得这个享元对象。可以使用单例模式来设计享元工厂,即让系统中只有一个享元工厂的实例。另外,为了让享元工厂能生成享元对象,需要将具体享元类作为享元工厂的内部类。

简单的例子

Flyweight的抽象类Flyweight.java

package Flyweight;public interface Flyweight {
public double getHeight(); //返回内部数据 public double getWidth(); public double getLength(); public void printMess(String mess); //使用参数mess获取外部数据}

Flyweight Factory的实现类FlyweightFactory.java

package Flyweight;import java.util.HashMap;public class FlyweightFactory {
private HashMap
hashMap; static FlyweightFactory factory = new FlyweightFactory(); public FlyweightFactory() { this.hashMap = new HashMap
(); } public static FlyweightFactory getFactory() { return factory; } public synchronized Flyweight getFlyweight(String key) { if (hashMap.containsKey(key)) { return hashMap.get(key); } else { double width = 0,height = 0,lenght = 0; String[] str = key.split("#"); width = Double.parseDouble(str[0]); height = Double.parseDouble(str[1]); lenght = Double.parseDouble(str[2]); Flyweight ft = new ConcreteFlyweight(width, height, lenght); hashMap.put(key, ft); return ft; } } class ConcreteFlyweight implements Flyweight { private double width; private double height; private double lenght; public ConcreteFlyweight(double width, double height, double lenght) { this.width = width; this.height = height; this.lenght = lenght; } @Override public double getHeight() { return height; } @Override public double getWidth() { return width; } @Override public double getLength() { return lenght; } @Override public void printMess(String mess) { System.out.println(mess); System.out.print("宽度:" + width); System.out.print("高度:" + height); System.out.print("长度:" + lenght); } }}

需要使用共享数据的类Car.java

package Flyweight;public class Car {
Flyweight flyweight; String name, color; int power; public Car(Flyweight flyweight, String name, String color, int power) { this.flyweight = flyweight; this.name = name; this.color = color; this.power = power; } public void print() { System.out.println("名称:" + name); System.out.println("颜色:" + color); System.out.println("功率:" + power); System.out.println("宽度:" + flyweight.getWidth()); System.out.println("高度:" + flyweight.getHeight()); System.out.println("长度:" + flyweight.getLength()); }}

测试类Application.java

package Flyweight;public class Application {
public static void main(String[] args) { FlyweightFactory factory = FlyweightFactory.getFactory(); double width = 1.82, height = 1.47, lenght = 5.12; String key = "" + width + "#" + height + "#" + lenght; Flyweight flyweight = factory.getFlyweight(key); Car audiA60ne = new Car(flyweight, "奥迪A6", "黑色", 128); Car audiA6Two = new Car(flyweight, "奥迪A6", "灰色", 160); //audiA60ne和audiA6Two没有向享元传递外部数据,而是获取享元的内部数据 audiA60ne.print(); audiA6Two.print(); width = 1.77; height = 1.45; lenght = 4.63; key = "" + width + "#" + height + "#" + lenght; Car audiA40ne = new Car(flyweight, "奥迪A4", "蓝色", 126); Car audiA4Two = new Car(flyweight, "奥迪A4", "红色", 138); //audiA40ne和audiA4Two向享元传递外部数据,这些数据是不共享的 flyweight.printMess("名称: 奥迪A4 颜色:蓝色 功率:126"); flyweight.printMess("名称: 奥迪A4 颜色:红色 功率:138"); }}

执行结果

享元模式的优点

  • 使用享元模式可以节省内存的开销,特别适合处理大量细粒度对象,这些对象的许多属性值是相同的,而且一旦创建则不容许修改。
  • 享元模式中的享元可以使用方法的参数接收外部状态中的数据,但外部状态数据不会干扰到享元中的内部数据,这就使享元可以在不同的环境中被共享。

适用享元模式的情景

下列情况之一就可以考虑使用享元模式:

  • 一个应用程序使用大量的对象,这些对象之间部分属性本质上是相同的,这时应使用享元来封装相同的部分。
  • 对象的多数状态都可变为外部状态,就可以考虑将这些对象作为系统中的享元来使用。

下载源码请到

转载地址:http://kvwva.baihongyu.com/

你可能感兴趣的文章
留德十年
查看>>
迷人的卡耐基说话术
查看>>
PHP导出table为xls出现乱码解决方法
查看>>
PHP问题 —— 丢失SESSION
查看>>
Java中Object类的equals()和hashCode()方法深入解析
查看>>
数据库
查看>>
Vue------第二天(计算属性、侦听器、绑定Class、绑定Style)
查看>>
dojo.mixin(混合进)、dojo.extend、dojo.declare
查看>>
Python 数据类型
查看>>
iOS--环信集成并修改头像和昵称(需要自己的服务器)
查看>>
PHP版微信权限验证配置,音频文件下载,FFmpeg转码,上传OSS和删除转存服务器本地文件...
查看>>
教程前言 - 回归宣言
查看>>
PHP 7.1是否支持操作符重载?
查看>>
Vue.js 中v-for和v-if一起使用,来判断select中的option为选中项
查看>>
Java中AES加密解密以及签名校验
查看>>
定义内部类 继承 AsyncTask 来实现异步网络请求
查看>>
VC中怎么读取.txt文件
查看>>
如何清理mac系统垃圾
查看>>
企业中最佳虚拟机软件应用程序—Parallels Deskto
查看>>
送给“正在纠结”、“准备纠结”的前端开发们
查看>>