设计模式15——享元模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用,主要是下面的UML图可以起到大作用,在你学习过一遍以后可能会遗忘,忘记了不要紧,只要看一眼UML图就能想起来了。同时也请大家多多指教。

享元模式(Flyweight)

是一种结构型模式。

目录

一、概述

1.1、先给出通用的UML图:

二、举例

2.1、简单举例认识此模式:

2.2、举例:


一、概述

复制代码
1、运用共享技术有效地支持大量细粒度的对象;
复制代码
2、享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够大幅度地减少需要实例化的类的数量。如果能把那些参数转移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目;
复制代码
3、如果一个应用程序使用大量的对象,而大量的这些对象造成了很大的存储开销时;
复制代码
4、内部状态存储在享元对象(目标对象)中,它包含了独立于其他对象的信息,这些信息使得享元对象可以被分享;

5、外部状态取决享元对象(目标对象)的所在场景,根据场景而变化,因为是动态变化的所以不能够共享。但有时会根据需要将外部状态传递给享元对象;

6、对象的大多数状态可以是外部状态,如果可以从对象中删除外部状态,那么可以用相对较少的共享对象取代很多组对象;那么此时可以考虑使用享元模式。

(注1:'粒度'是被用来描述对象大小的。如:我们将 淘宝应用程序 和 购物车功能 看做两个对象,那么我们可以说 淘宝 比起 购物车 粒度要大,或者说 购物车 比起 淘宝 粒度要小)

(注2:享元模式和原型模式都是针对一堆相似类对象。不同的是:享元模式是缩减它们从而减少储存开销;而原型模式是优化它们创建的方式从而减少新增和复制的时间开销。并且两种模式思想完全相反。)

1.1、先给出通用的UML图:

(对模式的简单认识将在下面简单举例认识此模式中说明)

二、举例

2.1、简单举例认识此模式:

**2.1.1、**假设王五和老刘都要访问博客网站,按照以往的思维,那肯定是要实例化两个博客网站的,如下:

**2.1.2、**那我们先进行初步的抽象,将博客对象都分为两部分,个人信息和网站功能:

**2.1.3、**我们可以发现,上述两个博客的实例对象,除了个人信息部分,其他地方都一样,此时我们就可想到享元模式,尝试将个人信息这部分转移出来,也就是将不同的地方拎出来,然后将相同的部分只保留一份:

**2.1.4、**对比上面两张图可以看到,节省了一个功能部分的存储空间。同理要是有10个人,就会有10个个人信息部分,但功能部分还是只有一份。通过这样的设计就达到了节省空间的目的。也就是把变与不变的地方分开来分析与设计。

此外:

  • 目标对象(享元对象):博客网站
  • 内部状态:功能部分
  • 外部状态:个人信息部分

2.2、举例:

**2.2.1、**假设现有四个人,张三、李四、王五、老刘,其中张三和李四要访问淘宝,王五和老刘要访问博客,假设淘宝和博客功能一致,那么相比上面的举例,和上述一样将个人信息部分都拎出来,但要注意新加了个淘宝,我们可以得到:

这次是有两个网站实例淘宝、博客,和四个人的信息部分。再经过分析发现,博客和淘宝可以抽象出:它们都属于网站。这样可以把博客和淘宝当做网站名的外部状态分离出来。

2.2.2、对象之间的关系用UML图表示如下:

(具体的功能部分不是本例的重点,所以就假设淘宝和博客功能部分一样,或者说被抽象出去了)

此例将个人信息单独设计一个类,而淘宝和博客这个就只存储在String字符串中。而实际使用此模式时根据自己的需要可以灵活改变。

2.2.2、Java实现代码如下:

网站抽象类:

java 复制代码
abstract class WebSite {
    public abstract void use(User user);
}

具体网站:

java 复制代码
public class ConcreteWebSite extends WebSite {
    private String webName;

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

    @Override
    public void use(User user) {
        System.out.println("网站名:" + this.webName + ",用户名:" + user.getUserName());
    }
}

网站控制工厂:

java 复制代码
public class WebSiteFactory {
    private HashMap<String, WebSite> hashMap = new HashMap<>();

    public WebSite getWebSiteCategory(String key) {
        if (!hashMap.containsKey(key)) {
            hashMap.put(key, new ConcreteWebSite(key));
        }
        return hashMap.get(key);
    }

    public int getWebSiteCount() {
        return hashMap.size();
    }
}

用户:

java 复制代码
public class User {
    private String userName;

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

    public String getUserName() {
        return userName;
    }
}

主程序(发起请求的类):

java 复制代码
public class Main {
    public static void main(String[] args) {
        WebSiteFactory webSiteFactory = new WebSiteFactory();

        WebSite webSite1 = webSiteFactory.getWebSiteCategory("淘宝");
        webSite1.use(new User("张三"));

        WebSite webSite2 = webSiteFactory.getWebSiteCategory("淘宝");
        webSite2.use(new User("李四"));

        WebSite webSite3 = webSiteFactory.getWebSiteCategory("博客");
        webSite3.use(new User("王五"));

        WebSite webSite4 = webSiteFactory.getWebSiteCategory("博客");
        webSite4.use(new User("老刘"));

        System.out.println("网站总数为:" + webSiteFactory.getWebSiteCount());
    }
}

这里就不再举例了,可以把上面的Java例子复制到你本地,运行main函数试一下加深理解。这些代码都是我自己学习的时候根据一些教材手敲的,不存在bug可以直接运行。

如果觉得本文还不错,就请点个赞吧!如果有建议,也请评论指教和讨论!

相关推荐
马剑威(威哥爱编程)39 分钟前
读写锁分离设计模式详解
java·设计模式·java-ee
修道-032341 分钟前
【JAVA】二、设计模式之策略模式
java·设计模式·策略模式
G皮T4 小时前
【设计模式】结构型模式(四):组合模式、享元模式
java·设计模式·组合模式·享元模式·composite·flyweight
W_Meng_H4 小时前
设计模式-组合模式
设计模式·组合模式
吾与谁归in14 小时前
【C#设计模式(8)——过滤器模式(Adapter Pattern)】
设计模式·c#·过滤器模式
G皮T15 小时前
【设计模式】行为型模式(一):模板方法模式、观察者模式
java·观察者模式·设计模式·模板方法模式·template method·行为型模式·observer
iFlyCai18 小时前
23种设计模式的Flutter实现第一篇创建型模式(一)
flutter·设计模式·dart
zhouzhihao_0718 小时前
程序代码设计模式之模板方法模式(1)
java·设计模式·模板方法模式
xianwu54318 小时前
【设计模式】工厂模式
开发语言·c++·设计模式·简单工厂模式·抽象工厂模式
树懒_Zz1 天前
设计模式-状态模式(State)
设计模式·状态模式