设计模式之享元模式

享元模式是一种有效地支持大量细粒度对象复用的技术,通过区分内部状态和外部状态来实现共享。它包括抽象享元类、具体享元类、非共享具体享元类和享元工厂类。这种模式可以减少内存中对象的数量,但会使系统复杂化。示例代码展示了如何在Java中实现享元模式。在Integer类中,valueOf方法就是享元模式的一个应用。
摘要由CSDN通过智能技术生成

什么是享元模式

    享元模式是指运用共享技术有效的支持大量细粒度对象的复用。系统只使用少量的对象,而这些都很相似,状态变化小,可以实现对象的多次复用。
    享元模式中对象实现共享的关键是区分了内部状态和外部状态:
        内部状态:存储在对象内部并且不会随环境改变而改变的状态,内部状态可以共享。
        外部状态:随环境改变而改变,不可以共享的状态,是由客户端传入对象内部。多个外部状态之间是相互独立的。
    正因为对象区分了内部状态和外部状态,所以可以将相同内部状态的对象存储在享元池中,享元池中的对象是可以共享的,需要的时候直接从享元池中获取,实现对象的复用。
    享元模式包含以下几个角色:
        Flyweight(抽象享元类):通常是一个接口或抽象类,声明一些可以向外界提供享元对象内部状态的方法,同时也可以通过这些方法设置内部状态。
        ConcreteFlyweight(具体享元类):实现了抽象享元类,为内部状态提供了存储空间。
        UnSharedConcreteFlyweight(非共享具体享元类):并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可以设计为非共享具体享元类,当需要使用非共享具体享元类时可以直接实例化创建。
        FlyweightFactory(享元工厂类):享元工厂类用于创建并管理享元对象,将各个类型的的具体享元对象存储在一个享元池中,享元池一般设计为键值对集合结构。
    标准的享元模式结构即包含可以共享的具体享元类,也包含不可以共享的非共享具体享元类。即分为两种特殊的享元模式,单纯享元模式和复合享元模式:
        单纯享元模式:所有的具体享元类都是可以共享的,不存在非共享具体享元类。
        复合享元模式:将一些单纯享元对象使用组合模式加以组合,还可以形成复合享元对象,这样的复合享元对象本身不能共享,但是可以分解成单纯享元对象,后者可以共享。

享元模式的优缺点

优点
  1. 可以极大的减少内部中对象的数量,使得相同或相似的对象在内存中只保存一份。节约系统资源。
  2. 享元模式的外部状态相对独立,而且不会影响其内部状态,使得享元对象可以在不同的环境中被共享。
缺点
  1. 享元模式使得系统变复杂,需要分离出内部状态和外部状态,使得程序逻辑复杂化。
  2. 为了对象可以共享,享元模式需要将享元对象的部分状态外部化,而读取外部状态会使运行时间变长。

享元模式的应用场景

  1. 一个系统有大量相同或相似的对象。
  2. 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。

享元模式的案例

public class User {

    private String name;

    public User(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


}

// 抽象享元类
public abstract class WebSite {

    public abstract void use(User user);

}

// 具体享元类
public class ConcreteWebSite extends WebSite {

    private final String type;

    public ConcreteWebSite(String type) {
        this.type = type;
    }

    @Override
    public void use(User user) {
        System.out.println("网站的发布形式为:" + type + " 在使用中 .. 使用者是" + user.getName());
    }


}

// 享元工厂类
public class WebSiteFactory {

    private final ConcurrentHashMap<String, ConcreteWebSite> pool = new ConcurrentHashMap<>();

    /**
     * 根据网站的类型,返回一个网站, 如果没有就创建一个网站,并放入到池中,并返回
     *
     * @param type type
     * @return WebSite
     */
    public WebSite getWebSiteCategory(String type) {
        if (!pool.containsKey(type)) {
            //就创建一个网站,并放入到池中
            pool.put(type, new ConcreteWebSite(type));
        }
        return pool.get(type);
    }

    /**
     * 获取网站分类的总数 (池中有多少个网站类型)
     *
     * @return int
     */
    public int getWebSiteCount() {
        return pool.size();
    }
}

public static void main(String[] args) {
	// 创建一个工厂类
	WebSiteFactory factory = new WebSiteFactory();

	// 客户要一个以新闻形式发布的网站
	WebSite webSite1 = factory.getWebSiteCategory("新闻");

	webSite1.use(new User("tom"));

	// 客户要一个以博客形式发布的网站
	WebSite webSite2 = factory.getWebSiteCategory("博客");

	webSite2.use(new User("jack"));

	// 客户要一个以博客形式发布的网站
	WebSite webSite3 = factory.getWebSiteCategory("博客");

	webSite3.use(new User("smith"));
	
	System.out.println("网站的分类共=" + factory.getWebSiteCount());
}

在这里插入图片描述

享元模式在源码中的应用

Integer
public final class Integer extends Number implements Comparable<Integer> {

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    ......
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值