java设计模式之享元模式

享元模式的定义:

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

享元模式提供了减少对象数量从而改善应用所需的对象结构的方式。其宗旨是共享细粒度的对象,将多个对同一对象的访问集

中起来,不必为每个访问者都创建单独的对象,以此来降低内存的消耗,属于结构型设计模式。

享元模式的应用场景:

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

享元模式的UML类图:

 

 

 

 由上图可以看到,享元模式主要包含3个角色。

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

享元模式的通用写法:

package com.gupaoedu.vip.pattern.flyweight.general;

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

/* *
 * @Author liuyi
 * @Description //TODO 
 * @Date 2020/11/15 13:13 
 * @Param 
 * @return 
 **/
public class Client {
    public static void main(String[] args) {
        FlyweightFactory flyweightFactory = new FlyweightFactory();
        IFlyweight flyweight1 = flyweightFactory.getFlyweight("aa");
        IFlyweight flyweight2 = flyweightFactory.getFlyweight("bb");
        flyweight1.operation("a");
        flyweight2.operation("b");
    }

    interface IFlyweight {
        void operation(String extrinsicState);
    }

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

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

        public void operation(String extrinsicState) {
            System.out.println("Object address: " + System.identityHashCode(this));
            System.out.println("IntrinsicState: " + this.intrinsicState);
            System.out.println("ExtrinsicState: " + extrinsicState);
        }
    }

    // 享元工厂
    static class FlyweightFactory {

        private static Map<String, IFlyweight> pool = new HashMap<String, IFlyweight>();

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

使用享元模式实现简单的数据库连接池:

  我们在用java'操作数据库的时候,首先必须要创建Connection和数据建立连接,才能操作数据库,而创建和关闭连接都十分的

消耗性能。所以数据库连接池就产生了,它的基本原理是将Connection对象缓冲起来,每次取得时候从缓冲中取,用完之后再放回

缓冲中,达到资源重复利用得目的,代码如下:

package com.gupaoedu.vip.pattern.flyweight.pool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Vector;

/* *
 * @Author liuyi
 * @Description //TODO 
 * @Date 2020/11/15 13:34 
 * @Param 
 * @return 
 **/
public class ConnectionPool {

    private Vector<Connection> pool;

    private String url = "jdbc:mysql://localhost:3306/test";
    private String username = "root";
    private String password = "root";
    private String driverClassName = "com.mysql.jdbc.Driver";
    private int poolSize = 100;

    public ConnectionPool() {
        pool = new Vector<Connection>(poolSize);

        try{
            Class.forName(driverClassName);
            for (int i = 0; i < poolSize; i++) {
                Connection conn = DriverManager.getConnection(url,username,password);
                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);
    }
}

享元模式得内部状态和外部状态:

  享元模式得定义提出两个要求:细粒度和共享对象。因为要求细粒度,所以不可避免地会使对象数量多且性质相近,此时我们就将这些对象地信息

分为两个部分:内部状态和外部状态。

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

不可共享。

  比如连接池中的连接对象,保存了连接对象的用户名,密码,URL等信息,在创建对象的时候就设置好了,不会随着环境的改变而改变,所以这些属

于内部状态。而当每个连接要被收回利用时,我们需要将它标记为可用状态,这些属于外部状态。

享元模式的优点:

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

享元模式的缺点:

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

 

posted @ 2020-11-15 13:47  负重前行的小牛  阅读(190)  评论(0编辑  收藏  举报