Java描述设计模式(18):享元模式
本文源码:github·点这里 || gitee·点这里
一、使用场景
应用代码
public class c01_inscene { public static void main(string[] args) { string c0 = "cicada" ; string c1 = "cicada" ; system.out.println(c0 == c1); // true } }
string类型就是使用享元模式。string对象是final类型,对象一旦创建就不可改变。在java中字符串常量都是存在常量池中的,java会确保一个字符串常量在常量池中只有一个拷贝,其中c0和c1就是一个字符串常量。结果为:true,说明c0和c1两个引用都指向了常量池中的同一个字符串常量"cicada"。这样的设计避免了在创建n多相同对象时所产生的不必要的大量的资源消耗。
二、享元模式
1、基础简介
享元模式是对象的结构模式。享元模式以共享的方式高效地支持大量的细粒度对象。常用于系统底层开发,解决系统的性能问题。像数据库连接池,里面都是创建好的连接对象,在这些连接对象中有需要的则直接拿来用,避免重新创建。
2、模式图解
3、核心角色
- 抽象享元角色
给出一个抽象接口,以规定具体享元角色要实现的方法。
- 具体享元角色
实现抽象享元角色所规定出的接口。如果有内部状态的话,必须为内部状态提供存储能力。
- 享元工厂角色
负责创建和管理享元角色。必须保证享元对象可以被系统选择性共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果已经存在,直接返回该对象;如果系统中没有该享元对象,享元工厂角色就应当创建该享元对象。
4、内部外部状态
- 内部状态指对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变。
- 外部状态指对象得以依赖的一个标记,可以随环境改变而改变的、不可共享的状态。
5、源码实现
public class c02_flyweight { public static void main(string[] args) { flyweightfactory factory = new flyweightfactory(); flyweight fly = factory.factorymethod('c'); fly.printstate("one"); fly = factory.factorymethod('d'); fly.printstate("two"); fly = factory.factorymethod('c'); fly.printstate("san"); // 调用了三次工厂方法,只创建了两个对象 factory.poolinfo(); } } /** * 抽象享元角色类 */ interface flyweight { void printstate (string state); } /** * 具体享元角色类 */ class concreteflyweight implements flyweight { private character innerstate = null; public concreteflyweight (character state){ this.innerstate = state; } @override public void printstate(string state) { system.out.println("内部状态:" + this.innerstate); system.out.println("外部状态:" + state); } } /** * 享元工厂角色类 */ class flyweightfactory { // 模拟数据池 private map<character,flyweight> pool = new hashmap<>(); public flyweight factorymethod (character state){ //先从缓存中查找对象 flyweight fly = pool.get(state); if(fly == null){ fly = new concreteflyweight(state); pool.put(state, fly); } return fly; } public void poolinfo (){ system.out.println("数据池:"+pool); } }
三、jdk应用场景
- 测试代码块
public class c03_integer { public static void main(string[] args) { integer c1 = integer.valueof(127),c2 = integer.valueof(127) ; integer c3 = new integer(127),c4 = new integer(127) ; boolean flag1 = c1==c2 ,flag2 = c2==c3,flag3 = c3==c4 ; // true;false;false system.out.println(flag1+";"+flag2+";"+flag3); integer c5 = integer.valueof(222),c6=integer.valueof(222) ; // false system.out.println(c5==c6); } }
- 源码分析
public static integer valueof(int i) { if (i >= integercache.low && i <= integercache.high) return integercache.cache[i + (-integercache.low)]; return new integer(i); }
这里valueof方法的意思就是,如果传入的数据在 (-128) 到 (127) 之间,则从缓存中直接返回,否则创建一个新的integer对象。
四、模式总结
享元模式能够解决重复对象的内存浪费的问题,当系统中有大量相似对象,需要缓冲池时。不需一直创建新对象,可以从缓冲池里拿。这样可以降低系统内存,同时提高效率。经典的应用场景就是池技术,string常量池、数据库连接池、缓冲池等等都是享元模式的应用,享元模式是池技术的重要实现方式。享元模式使得系统更加复杂。为了使对象可以共享,需要时刻管理对象的状态变化,这使得程序的逻辑变得复杂。
五、源代码地址
github·地址 https://github.com/cicadasmile/model-arithmetic-parent gitee·地址 https://gitee.com/cicadasmile/model-arithmetic-parent
上一篇: 牛排洋葱怎么做好吃?它们怎么可以这么配!