设计模式-享元模式

一、享元模式介绍

享元模式(Flyweight Pattern)也叫蝇量模式,主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。

它常用与系统底层的开发,解决系统地性能问题。像数据库连接池,里面都是创建好的连接对象,在这些连接中有我们需要的则直接拿来用,避免重新创建,如果没有我们需要的,则创建一个。

享元模式角色

  • FlyWeight:是抽象的享元角色,它是产品抽象类,定义出对象的外部状态和内部状态。
    • 内部状态:存储在享元对象内部且不会随环境改变而改变。
    • 外部状态:对象得以依赖的一个标记,是随环境改变而改变、不可共享的状态。
  • ConcreteFlyWeight:是具体的享元角色,实现抽象角色定义相关业务。
  • UnSharedConcreteFlyWeight:是不可共享的角色,一般不会出现在享元工厂。
  • FlyWeightFactory:享元工厂类,用于构建一个池容器(集合),同时提供从池中获取对象方法。

此处我们有一个诉求

  • 发布一个小型网站,不同客户希望以不同方式进行发布(包括但不限于微博、博客、新闻等形式)。
  • 传统实现方式:直接复制粘贴后根据客户需求再进行定制修改。
  • 传统方式会带来的问题:网站结构相似度很高,都不是高访问量网站,若通过此方式会造成服务器资源浪费。
  • 解决思路:采用享元模式(整合至一个网站,共享其相关的代码和数据,对于硬盘、内存、CPU、数据库空间等服务器资源都可以达成共享,更加节省资源的情况下,也利于维护和拓展。)

二、享元模式使用

2.1 示例关系:

2.2 代码实现:

/* *
 * 1. 外部状态:用户类。
 */

class User {

    private String name;

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

    public String getName() {
        return name;
    }

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



/* *
 * 2. 抽象享元角色:网站类。
 */

abstract class WebSite {

    public abstract void use(User user);
}



/* *
 * 3. 具体享元角色:具体网站类。
 */

class ConcreteWebSite extends WebSite {

    /* *
     * 内部状态:网站发布形式。
     */

    private String type;

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

    @Override
    public void use(User user) {
        System.out.println("网站发布形式是 :" + this.type +
                ",用户" + user.getName() + "正在使用网站...");
    }
}



/* *
 * 4. 享元工厂:控制内部状态。
 */

class WebSiteFactory {

    private Map<String, ConcreteWebSite> pool = new HashMap<>(8);

    /* *
     * 获取网站类型。
     */

    public WebSite getWebSiteCategory(String type) {
        // 如果没有该网站发布类型,就在池中创建一个。
        if (!pool.containsKey(type)) {
            pool.put(type, new ConcreteWebSite(type));
        }
        return pool.get(type);
    }

    /* *
     * 获取网站发布种类(当前池的大小)。
     */

    public int getWebSiteCount() {
        return this.pool.size();
    }
}



/* *
 * 客户端调用。
 */

public class Client {

    public static void main(String[] args) {
        WebSiteFactory factory = new WebSiteFactory();
        factory.getWebSiteCategory("微博").use(new User("tom"));
        factory.getWebSiteCategory("微博").use(new User("jack"));
        factory.getWebSiteCategory("知乎").use(new User("lucas"));
        factory.getWebSiteCategory("微信公众号").use(new User("jan"));

        System.out.println("当前网站分类共有" + factory.getWebSiteCount() + "种。");
        // 网站发布形式是 :微博,用户tom正在使用网站...
        // 网站发布形式是 :微博,用户jack正在使用网站...
        // 网站发布形式是 :知乎,用户lucas正在使用网站...
        // 网站发布形式是 :微信公众号,用户jan正在使用网站...
        // 当前网站分类共有3种。
    }

}

三、享元模式总结

优点

  • 大大减少了对象的创建,降低了程序内存的占用,提升了效率

缺点

  • 提高了系统的复杂度,需要分离出内部状态和外部状态。一般外部状态具有固化特性,不应该随着内部状态改变而改变,这是使用享元模式需要注意的地方。

应用场景

  • 当系统中有大量对象消耗掉大量内存,并且这些对象的状态大部分可以外部化时,就可以考虑从使用该模式。
  • String常量池、数据库连接池、缓冲池等等都是享元模式的应用,该模式是“池技术”的重要实现方式。
  • JDKInteger类。

四、结束语


“-------怕什么真理无穷,进一寸有一寸的欢喜。”

微信公众号搜索:饺子泡牛奶

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值