`

享元设计模式

 
阅读更多
一 享元模式介绍:

1.1 使用享元模式有什么好处?
享元模式是对象池的一种实现,主要目的是用来尽可能减少内存使用量。适合于存在大量重复对象的场景,来缓存可共享的对象,达到对象共享,避免创建过多对象的效果,这样可以提升性能。

1.2 关于享元对象?
享元对象中的部分状态可以共享,可以共享的状态为内部状态(内蕴状态),内部状态不会随环境变化,不可共享的状态是外部状态(外蕴状态),外部状态随外部环境变化。

1.3 享元模式的核心—-如何缓存?
在享元模式中会建立一个对象容器,可以是 一个Map,它的键是享元对象的内部状态,它的值就是享元对象本身。客户端程序通过这个内部状态从享元工厂中获取享元对象,如果有缓存则使用缓存对象,如果没有则创建一个享元对象并且存入容器,这样一来就避免了创建多个对象的问题。

二 享元模式的UML类图

享元模式分为单纯享元模式和复合享元模式两种,单纯享元模式的UML类图如图:
角色介绍:
(1)Flyweight: 抽象对象基类或者接口,为具体享元角色规定了必须实现的方法,外在状态就是以参数的形式通过此方法传入。
(2)ConcreteFlyweight: 具体享元角色,实现抽象角色规定的方法,并负责内部状态提供存储空间。
(3)FlyweightFactory:享元工厂角色。负责管理享元对象池和创建享元对象,是实现对象缓存的核心。
(4)Client:客户端角色。维护享元对象的引用和调用对象相应的方法。

这里写图片描述

复合享元模式的UML类图如图:
其中多了一个角色是复合享元角色ConcreteConpositeFlyweight: 它所代表的对象是不可以共享的,并且可以分解成为多个单纯享元对象的组合。

这里写图片描述

三 单纯享元模式的简单示例

示例背景:

我们都在某06网站买过火车票,在购票时,当我们设置好出发地和目的地之后,每次请求某06都会返回一个查询的车票结果,假设今年十一你要和你的女朋友从北京去厦门,而北京到厦门就一列火车Z307次。那么十一旅游高峰,很可能有数以万计的人都在不间断的请求从北京到厦门的Z307次车票数据,如果每次都创建一个查询的车票结果,那么必然会大量重复创建对象,销毁,使得GC任务很重。那么使用享元模式处理,创建一个享元对象Ticket,出发地和目的地是享元对象的内部状态,车票的种类(硬座,硬卧,软卧)为享元对象的外部状态,在用户查询北京到厦门的火车时,优先使用缓存,如果没有缓存则重新创建一个享元对象,并存放到Map容器中。

首先创建一个Ticket接口,该接口定义了展示车票信息的函数,这相当于类图中的Flyweight。

public interface Ticket {
    public void showTicketInfo(String siteType);//根据座位的类型展示车票结果信息
}

它的具体实现类是火车票TrainTicket,相当于UML类图中ConcreteFlyweight,是具体的享元角色。

/**
* Created by Administrator on 2016/4/14.
* 写一个Ticket的具体实现类TrainTicket;
*/
public class TrainTicket implements Ticket {
    public String from;  //始发地
    public String to;//目的地
    public String siteType;//座位type
    public int price;//价格

    public TrainTicket(String from, String to) {//构造方法
        this.from = from;
        this.to = to;
    }

    public void showTicketInfo(String siteType){
        price=new Random().nextInt(365);//随机价格
        Log.i("TAG","购买 从"+from+"到"+to+"的"+siteType+"的火车票"+",价格:"+price);
    }
}

真正实现缓存的是火车票工厂类TicketFactory,里面使用一个ConcurrentHashMap

/**真是实现对象缓存的类*/
public class TicketFactory {
    static Map<String,Ticket> stringTicketMap=new ConcurrentHashMap<>();
    public static Ticket getTicket(String from,String to){
        String key=from+"-"+to;//使用出发地和目的地作为Map的key
        if(stringTicketMap.containsKey(key)){
            Log.i("TAG","使用缓存==> "+key);
            return stringTicketMap.get(key);//获取以出发地和目的地为key的对象
        }else {
            Log.i("TAG","创建对象==> "+key);
            Ticket ticket=new TrainTicket(from, to);//创建对象
            stringTicketMap.put(key,ticket);
            return ticket;
        }
    }
}

我们在TicketFactory中添加了一个Map容器,Map容器我们使用的是ConcurrentHashMap,ConcurrentHashMap是一个线程安全的Map,里面引入了“分段锁”,相当于把一个大的Map拆分成N个小的线程安全的HashTable。上述代码中,用户请求的时候,先通过Key判断缓存是否已经有此对象,如果有则返回一个缓存对象;如果没有则先创建一个对象,并存放在Map中去。

客户端实现代码如下:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Ticket ticket01=TicketFactory.getTicket("北京","厦门");//每一个Ticket表示一个用户的请求
        ticket01.showTicketInfo("卧铺");
        Ticket ticket02=TicketFactory.getTicket("北京","厦门");
        ticket02.showTicketInfo("硬座");
        Ticket ticket03=TicketFactory.getTicket("北京","厦门");
        ticket03.showTicketInfo("软卧");
    }
}

看到Logcat打印的信息如下:

04-14 07:27:06.114 10763-10763/com.troy.flyweightpattern I/TAG: 创建对象==> 北京-厦门
04-14 07:27:06.114 10763-10763/com.troy.flyweightpattern I/TAG: 购买 从北京到厦门的卧铺的火车票,价格:56
04-14 07:27:06.125 10763-10763/com.troy.flyweightpattern I/TAG: 使用缓存==> 北京-厦门
04-14 07:27:06.125 10763-10763/com.troy.flyweightpattern I/TAG: 购买 从北京到厦门的硬座的火车票,价格:33
04-14 07:27:06.125 10763-10763/com.troy.flyweightpattern I/TAG: 使用缓存==> 北京-厦门
04-14 07:27:06.125 10763-10763/com.troy.flyweightpattern I/TAG: 购买 从北京到厦门的软卧的火车票,价格:252

从运行结果可以看出,只有第一次查询车票时创建了一次对象,后续的查询都使用的是Map容器中缓存的对象,其实就是相当于只有一个对象,避免了对象的重复创建和回收。在这个DEMO中,享元对象的内部状态就是出发地和目的地,内部状态不会发生变化;外部状态就是座位类型和价格,价格会随着座位类型的变化而变化。其实在JDK中String就是一种享元设计模式,String对象在第一次被定义后是缓存在常量池中的,当其他地方要用到的时候直接使用的是缓存,而不会重复创建。

以上就是对享元设计模式的理解,希望对大家的学习有所帮助,然后感受最深的一点就是设计模式在我们生活中无处不在,这个会后续和大家一起分享。
分享到:
评论

相关推荐

    java自动拆装箱及享元设计模式

    享元设计模式是一种结构型设计模式,其主要目的是为了节省内存空间,通过共享大量相似对象来减少内存消耗。在Java中,享元模式通常用于创建大量细粒度的对象,如字符常量池、字符串常量池等。 3. 享元模式的核心...

    java设计模式【之】享元模式【源码】【场景:多缓存可选模式】

    java设计模式【之】享元模式【源码】【场景:多缓存可选模式】 /** * 享元模式(预加载单例) * “元” 理解为 “同一地址对象” * 运用共享技术,减少对象的创建,降低对象的数量,降低内存消耗,提高性能 * ...

    【Java设计模式-源码】享元模式

    Java中的享元设计模式对于优化内存使用和提高应用程序性能至关重要。通过最小化创建的对象数量,它显著减少了内存占用。享元模式的主要目标是在相似对象之间尽可能多地共享数据,从而提高效率和性能。 ## 二、详细...

    软件设计模式——享元模式设计报告

    享元模式是一种软件设计模式,它的主要目的是为了提高性能,减少对象的创建,尤其是在大量相似对象需要被创建的情况下。在给定的咖啡店案例中,享元模式的应用可以帮助优化内存使用,避免为每杯咖啡的配料表分配独立...

    设计模式之享元模式

    享元模式是软件设计模式中的一种结构型模式,它的主要目的是为了提高性能,尤其是在处理大量对象时。在享元模式中,通过共享技术来有效支持大量细粒度的对象,从而减少内存消耗。《设计模式之禅》这本书是设计模式...

    设计模式的享元模式的例子

    享元模式是软件设计模式中的一种结构型模式,它的主要目的是通过共享大量细粒度对象来减少内存的使用,提高系统性能。在许多场景下,尤其是处理大量相似对象时,享元模式能显著减少内存开销。这个压缩包文件...

    Java设计模式之享元模式

    享元模式是软件设计模式中的一种结构型模式,它的核心思想是通过共享已经存在的对象来减少内存中的对象数量,从而提高系统性能。在Java中,享元模式常用于处理大量相似对象的场景,例如在图形界面中绘制大量相似的...

    总结JavaScript设计模式编程中的享元模式使用

    享元模式是软件工程中一种用于优化性能的设计模式,它通过共享相似对象的实例来减少内存使用或者计算的开销。在JavaScript编程中,尤其是处理DOM操作和大量相似对象时,享元模式的使用尤为关键。 享元模式的主要...

    设计模式-享元模式(讲解及其实现代码)

    享元模式是一种结构型设计模式,它通过共享已有对象来减少内存中对象的数量,从而达到降低系统内存占用、提高性能的目的。在软件工程中,当系统中存在大量相似或重复的对象时,享元模式尤为适用。 享元模式的核心是...

    设计模式(C#)之享元模式(Flyweight Pattern)

    享元模式是设计模式中的一种结构型模式,它主要通过共享已有对象来减少内存中对象的数量,从而提高系统性能。在C#编程中,享元模式尤其适用于那些创建大量相似对象且内存消耗较大的场景。本篇文章将深入探讨享元模式...

    设计模式学习笔记--Flyweight享元模式.docx

    享元模式是一种设计模式,属于构造型模式,其主要目的是减少对象的数量,通过共享大量相似对象的内部状态来节省内存。这种模式在处理大量细粒度对象时特别有用,能够有效地提高系统的性能。 享元模式的核心是...

    php设计模式案例详解

    5. **享元设计模式**:通过共享细粒度对象来减少内存消耗,通常用于减少大量相似对象的创建。 6. **备忘录设计模式**:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后恢复...

    C++设计模式代码资源13_Flyweight.zip

    总的来说,"C++设计模式代码资源13_Flyweight.zip"提供了C++实现享元设计模式的实例,对于学习和理解享元模式以及如何在实际项目中应用这一模式具有很高的参考价值。通过深入研究和实践,开发者能够更好地掌握如何...

    C#面向对象设计模式纵横谈(12):Flyweight 享元模式(结构型模式) (Level 300)

    在这个“C#面向对象设计模式纵横谈(12)”中,我们将深入探讨享元模式的概念、实现方式以及如何在实际项目中应用。 享元模式的核心思想是区分对象的状态和行为。状态分为内部状态和外部状态,其中内部状态是对象共有...

    享元模式代码+文档

    享元模式是一种结构型设计模式,它通过共享已有对象来减少系统中对象的数量,从而达到降低内存占用的目的。在软件工程中,当一个系统需要处理大量相似对象时,享元模式能够有效地提升性能,尤其在处理轻量级对象时...

    享元模式代码示例

    享元模式是一种结构型设计模式,它通过共享已有对象来减少内存中对象的数量,从而达到降低内存占用的目的。在面向对象编程中,当系统需要创建大量相似对象时,享元模式能够有效地提升性能,因为大部分对象是重复的,...

    学习php设计模式 php实现享元模式(flyweight)

    享元模式(Flyweight Pattern)是软件设计中的一种结构型设计模式,它通过共享技术来支持大量细粒度的对象,以此来降低内存中对象的数量。在PHP中实现享元模式,可以帮助我们优化程序性能,特别是在对象数目过多时,...

Global site tag (gtag.js) - Google Analytics