23种设计模式之享元模式

23种设计模式之享元模式

参考资料

下文如有错漏之处,敬请指正

一、简介

定义

运用共享技术对大量细粒度对象进行复用。

通过共享已经存在的对象、避免大量相似类的开销,从而提高系统资源的利用率。

享元模式中存在以下两种状态:

  • 内部状态,指不会随着环境的改变而改变的可共享部分。

  • 外部状态,指会随环境改变而改变的不可共享部分。

特点

  • 享元模式是一种结构型模式
  • 享元模式是池技术的重要实现方式

通用类图

在这里插入图片描述

享元模式的主要角色:

  • Flyweight

    抽象享元角色

    抽象产品类,定义出对象的外部状态和内部状态的接口或实现。

  • ConcreteFlyweight

    具体享元角色

    具体产品类,实现抽象享元角色定义的业务。该角色中需要注意的是内部状态处理应该与环境无关,不应该出现一个操作改变了内部状态,同时修改了外部状态,这是绝对不允 许的。

  • UnsharableFlyweight

    不可共享的享元角色

    是不需要要共享的外部对象,它以参数的形式注入具体享元的相关方法中。

  • FlyweightFactory

    享元工厂角色

    用于构建一个池容器,负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象放到池子并返回。

  • Client

    客户端角色

    客户端通过享元工厂获取享元对象。

优点

相同对象只保存一份,降低了系统中重复对象的数量,从而降低了系统中细粒度对象给内存带来的压力。

缺点

  • 为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。

  • 读取享元模式的外部状态会使得运行时间稍微变长。

应用场景

  • 常用于系统底层开发,解决系统的性能问题。如数据库连接池、String常量池、缓冲池。
  • 系统中存在大量的相似对象。
  • Spring的单例池
  • JDK中的Integer.valueOf()

二、享元模式

需求:

模拟一个文件夹里有三个共享资源,每个用户都可以获取资源,每个用户都有一个id,在获取资源时将会记录用户的id。

抽象享元角色:

package flyweight;

public abstract class Flyweight {

	//  内部状态(本程序未使用内部状态)
	private String intrinsic;

	//  外部状态
  //	在程序开发中,确认只需要一次赋值的属性则设置为final类型,避免无意修改导致逻辑混乱
	protected final String key;

	//  要求享元角色必须接受外部状态
	public Flyweight(String key) {
		this.key = key;
	}

	public String getKey() {
		return key;
	}

	//  定义业务操作
	//  获取资源
	public abstract void getResource(UnsharableFlyweight unsharableFlyweight);

}

具体享元角色:

package flyweight;

public class ConcreteFlyweight extends Flyweight{
    public ConcreteFlyweight(String key) {
        super(key);
    }

    @Override
    public void getResource(UnsharableFlyweight unsharableFlyweight) {
        System.out.println("id为"+unsharableFlyweight.getId()+"的用户正在获取资源"+this.getKey()+"……");
    }
}

不可共享的享元角色:

package flyweight;

public class UnsharableFlyweight {
	//  用户id
	private String id;


	public UnsharableFlyweight(String id) {
		this.id = id;
	}

	public String getId() {
		return id;
	}
}

享元工厂:

package flyweight;

import java.util.HashMap;
import java.util.Map;

public class FlyweightFactory {
	//  定义一个池容器
	private static Map<String, Flyweight> pool = new HashMap<>();

	//  享元工厂
	public static Flyweight getResource(String key) {
		//  需要返回的对象
		Flyweight resource = null;
		//  在池中没有该对象
		if (pool.containsKey(key)) {
			resource=pool.get(key);
			System.out.println("资源" + key + "已被创建,可以获取");
		} else {
			//  根据外部状态创建享元对象
			resource = new ConcreteFlyweight(key);
			System.out.println("资源" + key + "正在创建……");
			pool.put(key, resource);
		}
		return resource;
	}
}

Client:

package flyweight;

public class Client {
	public static void main(String[] args) {
		//  获取3个文件资源
		Flyweight resource1 = FlyweightFactory.getResource("1");
		Flyweight resource2 = FlyweightFactory.getResource("2");
		Flyweight resource3=FlyweightFactory.getResource("3");
		resource3=FlyweightFactory.getResource("3");

		//  定义3个用户
		UnsharableFlyweight user1 = new UnsharableFlyweight("A");
		UnsharableFlyweight user2 = new UnsharableFlyweight("B");
		UnsharableFlyweight user3 = new UnsharableFlyweight("C");

		//  获取指定的资源
		resource1.getResource(user1);
		resource2.getResource(user1);
		resource3.getResource(user2);
		resource3.getResource(user3);

		/**
		 * 输出结果:
		 * 资源1正在创建……
		 * 资源2正在创建……
		 * 资源3正在创建……
		 * 资源3已被创建,可以获取
		 * id为A的用户正在获取资源1……
		 * id为A的用户正在获取资源2……
		 * id为B的用户正在获取资源3……
		 * id为C的用户正在获取资源3……
		 */

	}
}

三、总结

享元模式是一个非常简单的模式,它可以大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值