享元模式详解

享元模式详解享元模式面向对象技术可以很好地解决一些灵活性或可扩展性问题 但在很多情况下需要在系统中增加类和对象个数 当对象数量太多时 将导致运行带价过高 带来性能下降等问题 享元模式正式为解决这一类问题而诞生的 享元模式 FlyweightPat 又称轻量级模式 是对象池的一种实现 类似于线程池 线程池可以不停的创建和销毁多个对象 消耗性能 提供了减少对象数量从而改善应用所需的对象结构的方式 其宗旨是共享细颗粒度对象 将多个对同一对象的访问集中起来 不必为每个访问者创建一个单独的对象 从此来降低内存的消耗

享元模式

// 抽象享元角色 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

(0)
上一篇 2026年3月16日 下午10:01
下一篇 2026年3月16日 下午10:01


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号