JAVA架构师之路九:设计模式之享元模式

JAVA架构师之路八:设计模式之装饰器模式

低头需要勇气,抬头需要底气

前几年,我们国家出现了一种新的经济,共享经济。比如说我们常见的:共享单车共享充电宝共享汽车等等。他们共同的特点就是对一件物品的重复利用。那么代码世界中,同样存在这种模式——享元模式。

1. 享元模式

定义

享元模式又称为轻量级模式,是对象池的一种实现。类似于线程池,线程池可以避免不停的创建和销毁多个对象,消耗性能。提供减少对象数量从而改善应用所需的对象结构的方式。
宗旨:共享细粒度对象,将多个对同一个对象的访问集中起来。
属于结构型模式

适用场景

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

优点

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

缺点

关注内、外部状态、关注线程安全问题
是系统、程序的逻辑复杂化

2. 火车票查询案例

火车票查询系统:我们每次查询出发站到目的站的火车票价,硬座,软座,硬卧等等。如果每个人查的时候都new 一个新的对象,那么对系统内存来讲,在春运的时候是灾难级的,我们可以利用享元模式来解决这个问题。下面看看代码怎么写

public interface ITicket {

    void showInfo(String bunk);
}
public class TrainTicket implements ITicket {

    private String from;

    private String to;

    private int price;

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

    public void showInfo(String bunk) {
        this.price = new Random().nextInt(500);
        System.out.println(from + "->" + to + ":" + bunk + "价格:" + this.price);
    }
}
public class TicketFactory {

    private static Map<String, ITicket> pool = new ConcurrentHashMap<String, ITicket>();

    public static ITicket queryTicket(String from, String to) {
        String key = from + "->" + to;
        if (pool.containsKey(key)) {
            System.out.println("使用缓存:" + key);
            return pool.get(key);
        }
        System.out.println("首次查询,创建对象");
        ITicket ticket = new TrainTicket(from, to);
        pool.put(key, ticket);
        return ticket;
    }
}

public class Test {

    public static void main(String[] args) {
        ITicket ticket = TicketFactory.queryTicket("北京西", "武汉");
        ticket.showInfo("硬座");
        ticket = TicketFactory.queryTicket("北京西", "武汉");
        ticket.showInfo("软座");
        ticket = TicketFactory.queryTicket("北京西", "武汉");
        ticket.showInfo("硬卧");
    }
}
首次查询,创建对象
北京西->武汉:硬座价格:125
使用缓存:北京西->武汉
北京西->武汉:软座价格:176
使用缓存:北京西->武汉
北京西->武汉:硬卧价格:305

在这里插入图片描述

3. 数据库连接池案例

数据库连接池也是一个很好的案例:每次要用Connection,如果大量的new,肯定会对系统的性能有一定的影响,如果利用享元模式,那这么写代码呢?

public class ConnectionPool {

    private Vector<Connection> pool;

    private final String url = "jdbc:mysql://localhost:3306/test";

    private final String username = "root";

    private final String password = "root";

    private final String driverClassName = "com.mysql.jdbc.Driver";

    private final int poolSize = 20;

    public ConnectionPool() {
        this.pool = new Vector<Connection>();
        for (int i = 0; i < poolSize; i++) {
            try {
                Class.forName(driverClassName);
                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);
    }
}

4. String中的享元模式

public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";
        String s3 = "he" + "llo";
        String s4 = "he" + new String("llo");
        String s5 = new String("hello");
        String s6 = s5.intern();
        String s7 = "h";
        String s8 = "ello";
        String s9 = s7 + s8;

        System.out.println(s1 == s2);// true
        System.out.println(s1 == s3);// true
        System.out.println(s1 == s4);//false
        System.out.println(s1 == s5);//false
        System.out.println(s4 == s5);//false
        System.out.println(s1 == s6);//true
        System.out.println(s1 == s9);//false
    }

String 本身会在系统运行过程中缓存常量,放在常量池中。直接赋值的方式初始化一个String,new 一个字符串的方式会在内存中新开辟一段空间,所以new的对象都不相等。s6s5.intern()方法返回值,是一个常量,所以s1 = s6s9 = s7 + s8,是s7s8相加,并不是常量相加。所以s1 != s9

5. Integer中的享元模式

public static void main(String[] args) {
        Integer a = Integer.valueOf(100);
        Integer b = 100;
        System.out.println(a == b); // true
        Integer c = Integer.valueOf(1000);
        Integer d = 1000;
        System.out.println(c == d); //false
    }

同样的代码,只是100换成了1000,结果就完全不相等。原理就是IntegervalueOf方法是用的缓存,缓存范围就是-128-127之间。这就是享元模式。

感谢您阅读本文,如果您觉得文章写的对您有用的话,请您点击上面的“关注”,点个赞,这样您就可以持续收到《JAVA架构师之路》的最新文章了。文章内容属于自己的一点点心得,难免有不对的地方,欢迎在下方评论区探讨,你们的关注是我创作优质文章的动力。

JAVA架构师之路十:设计模式之组合模式

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值