Java设计模式——享元模式

本咸鱼开始修炼内功了,加油,奥利给!!!

问题引出
如果我们做一个小型外包网站项目,有的客户想以新闻的形式发布,有的客户想以博客的形式发布,有的客户想以微信公众号的形式发布,我们该怎么办?

传统解决方案
直接复制一份原网站,然后根据不同的需求进行修改,同时给每个网站租用一个空间
在这里插入图片描述在这里插入图片描述

享元模式

简介

  1. 享元模式(Flyweight Pattern)也称蝇量模式

  2. 享元模式能够解决重复对象的内存浪费问题,当系统中有大量相似对象,需要缓冲池时,不需要总是创建新对象,而是从缓冲池里拿,这样可以降低系统内存、提高效率

  3. 享元模式是池技术的重要实现方式,经典应用场景有String常量连接池、数据库连接池、缓冲池等
    在这里插入图片描述在这里插入图片描述
    注:享元模式是为数不多的只为提升系统性能而生的设计模式,他的主要作用是复用大对象(重量级对象),以节省内存空间和对象创建时间

外部状态和内部状态

  1. 内部状态指对象共享出来的信息,存储在享元对象内部且不会随环境的改变而改变(例如棋子的颜色)

  2. 外部状态指对象得以依赖的一个标记,是随环境改变而改变的、不可共享的状态(例如棋子的位置)

  3. 内部状态存储于ConcreteFlyweight对象(实现类)之中,而外部对象则应该考虑由客户端对象存储或计算。当调用Flyweight对象的操作时,将该状态传递给它。

为什么要使用享元模式

  • 假如1000人看一场围棋直播,棋盘上有300个棋子,如果不使用享元模式,每一个棋子就是一个实例,每个观看的人都有300个棋子的实例,那么就会有300000个棋子,这对服务器内存占用是非常大的

  • 使用享元模式,实例就会减少到两个(一个黑棋子对象,一个白棋子对象),棋子颜色是棋子的内部状态可共享,棋子位置是外部状态不可共享

享元模式实例

使用享元模式解决前面提出的网站外包问题
在这里插入图片描述

public 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;
    }

    @Override
    public String toString() {
        return name;
    }
}

// 抽象享元,定义共享对象的业务接口
public abstract class WebSite {
    public abstract void use(User user); // 抽象方法
}
// 具体的网站(具体享元类),实现抽象享元类的接口,完成某一具体逻辑
public class ConcreteWebSite extends WebSite {

    // 共享的部分(内部状态)
    private String type = ""; // 网站发布的形式(类型)

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

    @Override
    public void use(User user) {
        System.out.println("网站发布形式为:" + type + " , " + user +" 正在使用中...");
    }
}
// 网站工厂类,根据需要返回一个网站(享元模式的核心)
public class WebSiteFactory {

    // 集合,充当池的作业
    private HashMap<String, ConcreteWebSite> pool = new HashMap<>();

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

    // 获取网站分类总数(池中有多少网站类型)
    public int getWebSiteCount() {
        return pool.size();
    }
}
// 客户端,使用享元模式的组件
public class Client {
    public static void main(String[] args) {
        // 创建一个工厂
        WebSiteFactory factory = new WebSiteFactory();

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

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

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

        System.out.println("网站分类共:" + factory.getWebSiteCount() + "个");
    }
}
// 运行结果
网站发布形式为:新闻 , 客户1 正在使用中...
网站发布形式为:博客 , 客户2 正在使用中...
网站发布形式为:博客 , 客户3 正在使用中...
网站分类共:2个

结果分析
虽然有三个客户定制了网站,但其中有两个客户的需求是一样的,第一次创建的 “博客” 分类被复用,所以池中只有两个网站分类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值