享元设计模式

一、享元模式

1、定义

享元模式(Flyweight Pattern)又称作轻量级模式,是指提供减少对象数量从而改善应用所需的对象结构的方式。其宗旨是共享细粒度的对象,将多个对同一对象的访问集中起来,不必为每个访问者都创建一个单独的对象,以此来降低内存的消耗,属于结构型设计模式。

享元模式是对象池的一种实现,类似线程池,线程池可以避免不停地创建和销毁对个对象,消耗性能。

享元模式的本质是缓存共享对象,降低内存消耗。

2、结构

(1)模式的结构

主要角色如下:

  • 抽象享元角色(IFlyweight):享元对象抽象基类或者接口,同时定义出了对象的外部状态和内部状态的接口或实现。
  • 具体享元角色(ConcreteFlyweight):实现抽象角色定义的业务。该角色的内部状态处理应该与环境无关,不会出现一个操作改变内部状态、同时修改了外部状态的情况。
  • 享元工厂(FlyweightFactory):负责管理享元对象池和创建享元对象。

(2)享元模式的内部状态和外部状态

享元模式把一个对象的状态分为内部状态和外部状态

  • 内部状态:指对象共享出来的信息,存储在享元对象内部,并且不会随环境的改变而改变。
  • 外部状态:指对象得以依赖的一个标记,随环境的改变而改变,不可共享。

比如:连接池中的连接对象,保存在连接对象中的用户名、密码、URL等信息,在创建对象时就已经设置好了,不会随环境的改变而改变,这些为内部状态。而当每个连接对象要被回收利用时,我们需要将它标记为可用状态,这些为外部状态。

3、优缺点

优点:

  • 减少对象的创建,降低了内存中对象的数量,降低系统的内存,提高效率。
  • 减少内存之外的其他资源占用。

缺点:

  • 关注内、外部状态,关注线程安全问题。
  • 使系统、程序的逻辑复杂。

4、使用场景

  • 经常应用于系统底层的开发,来解决系统的性能问题。
  • 系统有大量相似对象,需要缓冲池的场景。

5、在框架源码中使用

  • Java中的 String类,Integer类中的IntegerCache等。
  • Apache源码中的 对象池(GenericObjectPoo l)。

二、模式的通用实现

代码如下:

public class FlyweightPattern {
    public static void main(String[] args) {
        IFlyweight flyweight1 = FlyweightFactory.getFlyweight("i-aaa");
        IFlyweight flyweight2 = FlyweightFactory.getFlyweight("i-bbb");
        IFlyweight flyweight3 = FlyweightFactory.getFlyweight("i-aaa");

        flyweight1.operation("e-123");
        flyweight1.operation("e-456");
        flyweight3.operation("e2-123");
    }
}

// 抽象享元角色

interface IFlyweight{
    void operation(String extrinsicState);
}

// 具体享元角色
class ConcreteFlyweight implements IFlyweight{
    private String intrinsicState;

    public ConcreteFlyweight(String intrinsicState) {
        this.intrinsicState = intrinsicState;
    }

    @Override
    public void operation(String extrinsicState) {
        System.out.println("对象 哈希地址:" + System.identityHashCode(this));
        System.out.println("内部状态:" + this.intrinsicState);
        System.out.println("外部状态:" + extrinsicState);
    }
}

// 享元工厂
class FlyweightFactory{
    private static Map<String, IFlyweight> pool = new HashMap<>();

    private FlyweightFactory() {
    }

    public static IFlyweight getFlyweight(String intrinsicState){
        // 由于内部状态具备不变性,所以作为缓存的键
        if(!pool.containsKey(intrinsicState)){
            IFlyweight flyweight = new ConcreteFlyweight(intrinsicState);
            pool.put(intrinsicState, flyweight);
            return flyweight;
        }
        return pool.get(intrinsicState);
    }
}

在这里插入图片描述

三、模式的应用实例

以数据库连接池为例,Connection连接对象再使用之前我们需要提前创建好并缓存起来,使用完毕之后,需要在放回去,来达到资源重复利用的目的。

public class ConnectionPool {
	private Vector<Connection> pool;

	private String url = "jdbc:mysql://localhost:3306/test_db";
	private String username = "root";
	private String pazzword = "123456";
	private String driverClassName = "com.mysql.cj.jdbc.Driver";
	private int poolSize = 100;

	public ConnectionPool() {
		pool = new Vector<>(poolSize);
		try {
			Class.forName(driverClassName);
			for (int i = 0; i < poolSize; i++) {
				Connection conn = DriverManager.getConnection(url, username, pazzword);
				pool.add(conn);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public synchronized Connection getConnection(){
		if(pool.size() > 0){
			Connection conn = pool.get(0);
			pool.remove(conn);
			return conn;
		}
		return null;
	}

	public synchronized void release(Connection conn){
		pool.add(conn);
	}

}

测试:

	public static void main(String[] args) throws SQLException {
		ConnectionPool connectionPool = new ConnectionPool();
		Connection conn = connectionPool.getConnection();

		conn.setAutoCommit(false);
		conn.createStatement();
		//conn.commit();

		connectionPool.release(conn);
	}

– 求知若饥,虚心若愚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值