享元模式
// 抽象享元角色 public interface IFlyweight {
void operation(String extrinsicState); }
具体享元角色(ConcreteFlyweight):实现抽象角色定义的业务。该角色的内部状态处理应该与环境无关,不能出现会有一个操作改变内部状态 ,同时修改了外部状态;
// 具体享元角色 public 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); } }
享元工厂(FlyweightFactory):负责管理享元对象池和创建享元对象。
// 享元工厂 public 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); } }
测试Test:
public class Test {
public static void main(String[] args) {
IFlyweight flyweight1 = FlyweightFactory.getFlyweight("aa"); IFlyweight flyweight2 = FlyweightFactory.getFlyweight("bb"); flyweight1.operation("a"); flyweight2.operation("b"); } }
享元模式的应用场景
使用享元模式实现共享池业务
public interface ITicket{
void showInfo(String bunk); }
然后,创建TrainTicket接口:
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(String.format("%s->%s:%s价格:%s 元", this.from, this.to, bunk, this.price)); } }
最后创建TicketFactory类:
class TicketFactory {
private static Map<String, ITicket> sTicketPool = new ConcurrentHashMap<String,ITicket>(); public static ITicket queryTicket(String from, String to) {
String key = from + "->" + to; if (TicketFactory.sTicketPool.containsKey(key)) {
System.out.println("使用缓存:" + key); return TicketFactory.sTicketPool.get(key); } System.out.println("首次查询,创建对象: " + key); ITicket ticket = new TrainTicket(from, to); TicketFactory.sTicketPool.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("硬卧"); } }
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); } }
测试类的编写:
public class Test {
public static void main(String[] args) {
ConnectionPool pool = new ConnectionPool(); Connection conn = pool.getConnection(); System.out.println(conn); } }
这样的连接池,普遍应用于开源框架,有效提升底层的运行性能。
享元模式在源码中的应用
1、String中的享元模式
public class StringTest {
public static void main(String[] args) {
String s1 = "hello"; String s2 = "hello"; String s3 = "he" + "llo"; String s4 = "hel" + new String("lo"); 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==s9);//false System.out.println(s4==s5);//false System.out.println(s1==s6);//true } }
2、Integer中的享元模式
在举一个例子,大家都非常熟悉的对象Integer,也用到了享元模式,其中暗藏玄机,我们来看:
public class IntegerTest {
public static void main(String[] args) {
Integer a = Integer.valueOf(100); Integer b = 100; Integer c = Integer.valueOf(1000); Integer d = 1000; System.out.println("a==b:" + (a==b)); System.out.println("c==d:" + (c==d)); } }
3、Long中的享元模式

同理,Long中也有缓存,不过不能指定缓存最大值。
Apache Commons Pool2中的享元模式
享元模式的内部状态和外部状态
享元模式的优缺点
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227067.html原文链接:https://javaforall.net
