享元模式(Flyweight Pattern)又称作轻量级模式,是指提供减少对象数量从而改善应用所需的对象结构的方式。其宗旨是共享细粒度的对象,将多个对同一对象的访问集中起来,不必为每个访问者都创建一个单独的对象,以此来降低内存的消耗,属于结构型设计模式。
享元模式是对象池的一种实现,类似线程池,线程池可以避免不停地创建和销毁对个对象,消耗性能。
享元模式的本质是缓存共享对象,降低内存消耗。
(1)模式的结构
主要角色如下:
(2)享元模式的内部状态和外部状态
享元模式把一个对象的状态分为内部状态和外部状态。
比如:连接池中的连接对象,保存在连接对象中的用户名、密码、URL等信息,在创建对象时就已经设置好了,不会随环境的改变而改变,这些为内部状态。而当每个连接对象要被回收利用时,我们需要将它标记为可用状态,这些为外部状态。
优点:
缺点:
代码如下:
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;}@Overridepublic void operation(String extrinsicState) {System.out.println("对象 哈希地址:" + System.identityHashCode(this));System.out.println("内部状态:" + this.intrinsicState);System.out.println("外部状态:" + extrinsicState);}
}// 享元工厂
class FlyweightFactory{private static Map 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 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);}
– 求知若饥,虚心若愚。