首页 > 编程语言 >Java设计模式之享元模式

Java设计模式之享元模式

时间:2023-10-08 16:23:34浏览次数:30  
标签:享元 Java 对象 BoxFactory getShape AbstractBox 设计模式 public

1.1. 概述

定义: 运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象的开销,从而提高系统资源的利用率。  

1.2. 结构

享元(Flyweight )模式中存在以下两种状态: 1. 内部状态,即不会随着环境的改变而改变的可共享部分。 2. 外部状态,指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化。 享元模式的主要有以下角色:      *抽象享元角色(Flyweight):通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公 共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法 来设置外部数据(外部状态)。     *具体享元(Concrete Flyweight)角色 :它实现了抽象享元类,称为享元对象;在具体享元 类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享 元类提供唯一的享元对象。     *非享元(Unsharable Flyweight)角色 :并不是所有的抽象享元类的子类都需要被共享,不 能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过 实例化创建      *享元工厂(Flyweight Factory)角色 :负责创建和管理享元角色。当客户对象请求一个享元 对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在 的话,则创建一个新的享元对象。

1.3.案例实现

【例】俄罗斯方块 下面的图片是众所周知的俄罗斯方块中的一个个方块,如果在俄罗斯方块这个游戏中,每个不同的方块 都是一个实例对象,这些对象就要占用很多的内存空间,下面利用享元模式进行实现。

先来看类图:

代码如下: 俄罗斯方块有不同的形状,我们可以对这些形状向上抽取出AbstractBox,用来定义共性的属性和行为。/**
 * @version v1.0
 * @ClassName: AbstractBox
 * @Description: 抽象享元角色
 * @Author: 黑马程序员
 */
public abstract class AbstractBox {

    //获取图形的方法
    public abstract String getShape();

    //显示图形及颜色
    public void display(String color) {
        System.out.println("方块形状:" + getShape() + ", 颜色:" + color);
    }
}

 

接下来就是定义不同的形状了,IBox类、LBox类、OBox类等。
/**
 * @version v1.0
 * @ClassName: IBox
 * @Description: I图形类(具体享元角色)
 * @Author: 黑马程序员
 */
public class IBox extends AbstractBox {

    public String getShape() {
        return "I";
    }
}


/**
 * @version v1.0
 * @ClassName: IBox
 * @Description: L图形类(具体享元角色)
 * @Author: 黑马程序员
 */
public class LBox extends AbstractBox {

    public String getShape() {
        return "L";
    }
}



/**
 * @version v1.0
 * @ClassName: IBox
 * @Description: O图形类(具体享元角色)
 * @Author: 黑马程序员
 */
public class OBox extends AbstractBox {

    public String getShape() {
        return "O";
    }
}

 提供了一个工厂类(BoxFactory),用来管理享元对象(也就是AbstractBox子类对象),该工厂类对象只需要一个,所以可以使用单例模式。并给工厂类提供一个获取形状的方法。 

/**
 * @version v1.0
 * @ClassName: BoxFactory
 * @Description: 工厂类,将该类设计为单例
 * @Author: 黑马程序员
 */
public class BoxFactory {

    private HashMap<String,AbstractBox> map;

    //在构造方法中进行初始化操作
    private BoxFactory() {
        map = new HashMap<String, AbstractBox>();
        map.put("I",new IBox());
        map.put("L",new LBox());
        map.put("O",new OBox());
    }

    //提供一个方法获取该工厂类对象
    public static BoxFactory getInstance() {
        return factory;
    }

    private static BoxFactory factory = new BoxFactory();

    //根据名称获取图形对象
    public AbstractBox getShape(String name) {
        return map.get(name);
    }
}

 

 客户端类:

/**
 * @version v1.0
 * @ClassName: Client
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public class Client {
    public static void main(String[] args) {
        //获取I图形对象
        AbstractBox box1 = BoxFactory.getInstance().getShape("I");
        box1.display("灰色");

        //获取L图形对象
        AbstractBox box2 = BoxFactory.getInstance().getShape("L");
        box2.display("绿色");

        //获取O图形对象
        AbstractBox box3 = BoxFactory.getInstance().getShape("O");
        box3.display("灰色");

        //获取O图形对象
        AbstractBox box4 = BoxFactory.getInstance().getShape("O");
        box4.display("红色");

        System.out.println("两次获取到的O图形对象是否是同一个对象:" + (box3 == box4));
    }
}

 

 1.5 优缺点和使用场景

1,优点 极大减少内存中相似或相同对象数量,节约系统资源,提供系统性能 享元模式中的外部状态相对独立,且不影响内部状态 2,缺点: 为了使对象可以共享,需要将享元对象的部分状态外部化,分离内部状态和外部状态,使程序逻辑复杂 3,使用场景: 一个系统有大量相同或者相似的对象,造成内存的大量耗费。 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。 在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应 当在需要多次重复使用享元对象时才值得使用享元模式。          

标签:享元,Java,对象,BoxFactory,getShape,AbstractBox,设计模式,public
From: https://www.cnblogs.com/carlors/p/17749486.html

相关文章

  • Java 应用启动脚本
    启动代码java-server-Xms4g-Xmx4g-Xss256k-XX:NewSize=512m-XX:MaxNewSize=512m-XX:+UseG1GC-XX:InitiatingHeapOccupancyPercent=40-XX:G1HeapRegionSize=8m-XX:+ExplicitGCInvokesConcurrent-XX:ParallelGCThreads=4-Dsun.rmi.dgc.server.gcInterval=36000000-Ds......
  • 设计模式之 State Pattern状态模式
    State模式允许对象在内部状态变化时,变更其行为,并修改其类;优点:定位指定状态的行为,并且针对不同状态来划分行为,使状态转换显式进行;适用:对象的行为依赖于其状态,并且该对象必须在运行时根据其状态修改其行为;操作具有大量的以及多部分组成的取决于对象状态的条件语句; publicc......
  • Appium+JAVA+IDEA环境搭建
    1、Java环境配置(基础,不再描述)2、AndroidSDK安装   (1)下载地址:https://www.androiddevtools.cn/#sdk-tools(下载后解压即可)      (2)配置环境变量ANDROID_HOME      (3)添加到Path路径(platform-tools文件夹需要SDKManger安装后出现)      (4)c......
  • Java的反射机制
    Java的反射机制前言能够分析类能力的程序称为反射,反射机制可以用来:在运行程序时分析类的能力;在运行时检查对象;实现泛型数组操作代码;利用Method对象;Class类在程序运行期间,Java运行时系统始终为所有对象维护一个「运行时类型信息标识」。这个信息会跟踪每个对象所属的类,J......
  • 设计模式之 Template Method模版方法
    TemplateMethod模式提供了不重写方法的前提下,允许子类重载部分方法的方法;在操作中定义算法的框架,将一些步骤由子类实现,该模式可以再不修改算法结构的情况下,让子类重新定义算法的特定步骤;优点:代码重用的基础技术;适用:想要一次实现算法的不变部分,而使用子类实现算法的可变行为;......
  • java代码注释和空行删除,软著源码
    notepad++替换,结合正则表达式处理匹配//单行注释//.*匹配/**多行注释*/注意需要非贪婪模式,所以有一个?使用/\*{2}[\s\S]*?\*/匹配空行^\s*\n上面多行注释的匹配,需要非贪婪模式如果没有那个问号,将会把这一整块都匹配进去,第一块多行注释的头/**和最后一个多行注释......
  • 设计模式(七)桥接
    一、定义将抽象部分与它的实现部分解耦,使两者都能够独立变化,桥接模式是一种结构型模式。二、描述包含以下四个角色:1、Abstraction(抽象类):它是用于定义抽象类的接口,通常是抽象类而不是接口,其中定义了一个Implementor(实现类接口)类型的对象并可以维护该对象,它与Implementor之间具......
  • mybatis出现错误 java lang NumberFormatException:For input string:A1
    使用mybatis,当使用map传参并且在iftest判断时使用map中所传的参数时,可能会产生如题的报错,具体报错信息见下图:分析这个错误,自己调试也找过度娘,“坚信”自己代码并没问题,但是问题始终无法解决。最后在一个帖子看到说iftest判断时,传入的参数跟匹配的值类型必须一致,于是调整了自己代......
  • JavaScript实现大文件分片上传处理
    我可以为你讲解如何实现JavaScript实现大文件分片上传处理,以下是具体的攻略步骤:步骤1:选择文件在实现大文件分片上传之前,第一步需要让用户选择一个文件。你可以在页面上加入一个文件选择表单,如下所示:<inputtype="file"name="file"id="file">步骤2:对文件进行分片处理当用户......
  • Java 队列Queue的一些基本操作与概念!!!!!!!!
    首先Java中的队列(Queue)是一种先进先出的数据结构。其中常见的一些基本操作与方法,包括:1、创建队列对象。例如:ArrayDeque、LinkedList等。2、入队操作。将元素添加到队列的末尾处,使用offer()方法。3、出队操作。从队列的头部移除并返回元素,使用poll()方法。......