JAVA语言设计模式--享元模式解析
小标 2018-12-19 来源 : 阅读 1388 评论 0

摘要:本文主要向大家介绍了JAVA语言设计模式--享元模式解析,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了JAVA语言设计模式--享元模式解析,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。


1 Facade Pattern 享元模式


目的:减少创建对象的数量,减少内存占用和提高性能;

实现:用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。



 

1.运用共享技术有效地支持大量细粒度对象的复用;系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用,如果未找到匹配的对象,则创建新对象;

 2.享元模式以共享的方式高效地支持大量细粒度对象的重用,享元对象能做到共享的关键是区分了内部状态(Intrinsic State)和外部状态(Extrinsic State)。



2 实现


代码场景:生成一个线程池,预定义了线程名字,如果客户端获取的线程存在则返回线程池中的该线程,如果不存在则新建一个线程。


2.1 代码实现


抽象享元类:AbstractThread


public abstract class AbstractThread {

    // 线程内部状态

    protected String threadName;

 

    public AbstractThread(String threadName) {

        this.threadName = threadName;

    }

 

    // 线程外部状态

    public void threadStatus(String threadStatus) {

        System.out.println(threadName + "当前外部状态为:" + threadStatus);

    }

 

    public abstract void excute();

}

   


具体享元类:ThreadA


public class ThreadA extends AbstractThread {

 

    public ThreadA(String threadName) {

        super(threadName);

    }

 

    @Override

    public void excute() {

        System.out.println("线程[" + threadName + "]开始执行任务~");

    }

 

}

   


具体享元类:ThreadB


public class ThreadB extends AbstractThread {

 

    public ThreadB(String threadName) {

        super(threadName);

    }

 

    @Override

    public void excute() {

        System.out.println("线程[" + threadName + "]开始执行任务~");

    }

 

}

   


具体享元类:ThreadNew 匹配不到时新增


public class ThreadNew extends AbstractThread {

 

    public ThreadNew(String threadName) {

        super(threadName);

    }

 

    @Override

    public void excute() {

        System.out.println("线程[" + threadName + "]开始执行任务~");

    }

 

}

   


享元工厂类:ThreadFactory


public class ThreadFactory {

    private static ThreadFactory threadFactory = new ThreadFactory();

    private Map<string, abstractthread=""> threadMap = new HashMap<string, abstractthread="">();

 

    private ThreadFactory() {

        AbstractThread threadA = new ThreadA("A");

        AbstractThread threadB = new ThreadB("B");

        threadMap.put("A", threadA);

        threadMap.put("B", threadB);

 

    }

 

    public static ThreadFactory getThreadFactory() {

        return threadFactory;

    }

 

    public AbstractThread getThread(String threadName) {

        // 如果想要获取的线程享元池中存在 则从享元池中获取

        if (threadMap.containsKey(threadName)) {

            return threadMap.get(threadName);

        }

        // 如果想要获取的线程享元池中不存在 则new一个

        else {

            ThreadNew threadNew = new ThreadNew(threadName);

            threadMap.put(threadName, threadNew);

            return threadNew;

        }

 

    }

}</string,></string,>

   


2.2 涉及角色


在享元模式结构图中包含如下几个角色:


Flyweight(抽象享元类):通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态)。


ConcreteFlyweight(具体享元类):它实现了抽象享元类,其实例称为享元对象;在具体享元类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象。


UnsharedConcreteFlyweight(非共享具体享元类):并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过实例化创建。

FlyweightFactory(享元工厂类):享元工厂类用于创建并管理享元对象,它针对抽象享元类编程,将各种类型的具体享元对象存储在一个享元池中,享元池一般设计为一个存储“键值对”的集合(也可以是其他类型的集合),可以结合工厂模式进行设计;当用户请求一个具体享元对象时,享元工厂提供一个存储在享元池中已创建的实例或者创建一个新的实例(如果不存在的话),返回新创建的实例并将其存储在享元池中。



 

享元的内部状态和外部状态简单介绍:

 (1) 内部状态是存储在享元对象内部并且不会随环境改变而改变的状态,内部状态可以共享。如字符的内容,不会随外部环境的变化而变化,无论在任何环境下字符“a”始终是“a”,都不会变成“b”。


 

(2) 外部状态是随环境改变而改变的、不可以共享的状态。享元对象的外部状态通常由客户端保存,并在享元对象被创建之后,需要使用的时候再传入到享元对象内部。一个外部状态与另一个外部状态之间是相互独立的。如字符的颜色,可以在不同的地方有不同的颜色,例如有的“a”是红色的,有的“a”是绿色的,字符的大小也是如此,有的“a”是五号字,有的“a”是四号字。而且字符的颜色和大小是两个独立的外部状态,它们可以独立变化,相互之间没有影响,客户端可以在使用时将外部状态注入享元对象中。


 
 

正因为区分了内部状态和外部状态,我们可以将具有相同内部状态的对象存储在享元池中,享元池中的对象是可以实现共享的,需要的时候就将对象从享元池中取出,实现对象的复用。通过向取出的对象注入不同的外部状态,可以得到一系列相似的对象,而这些对象在内存中实际上只存储一份。



2.3 调用


调用者:


public class Client {

    public static void main(String[] args) {

        // 获取享元工厂

        ThreadFactory threadFactory = ThreadFactory.getThreadFactory();

        // 获取共享元素

        AbstractThread thread1 = threadFactory.getThread("A");

        AbstractThread thread2 = threadFactory.getThread("B");

        // 获取新元素

        AbstractThread thread3 = threadFactory.getThread("C");

        // 线程执行任务

        thread1.excute();

        thread2.excute();

        thread3.excute();

 

        AbstractThread thread4 = threadFactory.getThread("A");

        // thread1和thread4获取的是同一个实例

        if (thread1 == thread4) {

            System.out.println("thread1 == thread4");

        }

    }

}

   


结果:


线程[A]开始执行任务~

线程[B]开始执行任务~

线程[C]开始执行任务~

thread1 == thread4

   


          

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved