结构型设计模式之享元模式

Posted 丨Jack_Chen丨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了结构型设计模式之享元模式相关的知识,希望对你有一定的参考价值。

@TOC

享元模式

概述

目的

 1、系统有大量相似对象。 

 2、需要缓冲池的场景。

例如

1、JAVA中的String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。 

2、数据库的数据池。

优缺点

优点:

1.减少对象的创建,降低内存中对象的数量,降低系统的内存,提高效率。

2.减少内存之外的其他资源占用。

缺点:

1.关注内、外部状态、关注线程安全问题。

2.提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。

主要角色

1.抽象享元角色(Flyweight)

2.具体享元角色(ConcreteFlyweight)

3.享元工厂(FlyweightFactory)

享元模式结构

内部状态和外部状态

内部状态指与外部状态

例如

public interface ITicket 
    /**
     * 查询票信息
     */
    void query();

创建具体享元角色

public class TrainTicket implements ITicket 
    /**
     * 出发地
     */
    private String from;
    /**
     * 目的地
     */
    private String to;
    /**
     * 票种类
     */
    private String type;
    /**
     * 票价
     */
    private int price;

    public TrainTicket(String from, String to, String type) 
        this.from = from;
        this.to = to;
        this.type = type;
    

    public void query() 
        this.price = new Random().nextInt(100);
        int num = new Random().nextInt(10);
        System.out.println(String.format("从%s到%s,%s,票价:%s元,剩余车票:%s", this.from, this.to, this.type, this.price, num));
    

创建享元工厂

将相同查询票的信息对象进行缓存,复用该对象进行查询,减少对象的创建,降低内存的压力。

public class TicketFactory 
    private static Map<String, ITicket> ticketPool = new ConcurrentHashMap<String, ITicket>();

    public static ITicket queryTicket(String from, String to, String type) 
        String key = "出发站:"+from + " 目的站:" + to + " 坐席类型:" + type;
        if (TicketFactory.ticketPool.containsKey(key)) 
            System.out.println("使用缓存查询:" + key);
            return TicketFactory.ticketPool.get(key);
        
        System.out.println("第一次查询,创建对象: " + key);
        ITicket ticket = new TrainTicket(from, to, type);
        TicketFactory.ticketPool.put(key, ticket);
        return ticket;
    

客户端调用

    public static void main(String[] args) 
        ITicket ticket = TicketFactory.queryTicket("A", "B", "特等座");
        ticket.query();

        ticket = TicketFactory.queryTicket("A", "B","一等座");
        ticket.query();

        ticket = TicketFactory.queryTicket("A", "B","特等座");
        ticket.query();
    
第一次查询,创建对象: 出发站:A 目的站:B 坐席类型:特等座
从A--->B,特等座,票价:38元,剩余车票:8

第一次查询,创建对象: 出发站:A 目的站:B 坐席类型:一等座
从A--->B,一等座,票价:0元,剩余车票:4

使用缓存查询:出发站:A 目的站:B 坐席类型:特等座
从A--->B,特等座,票价:62元,剩余车票:6

总结

享元模式实现数据库连接池

创建数据库连接池

@Data
public class ConnectionPool 

    private Vector<Connection> pool;

    private String url = "jdbc:mysql://localhost:3306/demo";
    private String username = "root";
    private String password = "123456";
    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();
        
    

    /**
     * 获取连接
     * @return
     */
    public synchronized Connection getConnection() 
        if (pool.size() > 0) 
            Connection conn = pool.get(0);
            pool.remove(conn);
            return conn;
        
        return null;
    

    /**
     * 释放归还连接
     * @param conn
     */
    public synchronized void release(Connection conn) 
        pool.add(conn);
    

使用数据库连接池

    public static void main(String[] args) 
        ConnectionPool connectionPool = new ConnectionPool();
        Connection conn = connectionPool.getConnection();
        System.out.println("获取一个连接:" + conn + "连接池中剩余:" + connectionPool.getPool().size());
        try 
            Thread.sleep(2000);
         catch (InterruptedException e) 
            throw new RuntimeException(e);
         finally 
            connectionPool.release(conn);
            System.out.println("归还连接池,连接池总数: " + connectionPool.getPool().size());
        
    
获取一个连接:com.mysql.jdbc.JDBC4Connection@7fad8c79连接池中剩余:99
归还连接池,连接池总数: 100

以上是关于结构型设计模式之享元模式的主要内容,如果未能解决你的问题,请参考以下文章

结构型模式之享元模式

结构型模式之享元

设计模式之享元模式(结构型)

设计模式之享元模式(结构型)

《精通Python设计模式》学习结构型之享元模式

揭秘设计模式之享元模式