ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

7享元模式

2020-12-29 09:01:18  阅读:133  来源: 互联网

标签:享元 状态 对象 模式 棋子 public


享元模式

享元模式(Flyweight Pattern) 是池技术的重要方式,可以降低大量的重复的、细粒度的类在内存中的开销。

1享元模式的定义

享元模式的英文原文是:Use sharing to support large numbers of fine-grained objects efficiently.
意思是:使用共享对象可有效的支持大量细粒度的对象。
享元模式是以共享模式高效的支持大量的细粒度对象。享元对象能做到共享的关键是区分内部状态(Internal State) 和外部状态(External State)。
  • 内部状态是存储在享元对象内部的、可以共享的信息,并且不会随环境改变而改变。
  • 外部状态是随环境改变而改变且不可以共享的状态。享元对象的外部状态必须有客户端保存,并且在享元对象被创建之后,在需要使用的时候再传入到享元对象的内部。

享元模式有4个角色:
  • 抽象享元(Flyweight )角色:该角色对享元类进行抽象,需要外部状态的操作可以通过参数的形式将外部状态传入。
  • 具体享元(Concrete Flyweight)角色:该角色实现抽象享元定义的业务,注意享元对象可以在系统内共享。
  • 享元工厂(FlyweightFactory)角色:构造一个池容器,并负责创建和管理享元角色,提供从池容器中获得对象的方法,保证享元对象可以被系统适当的共享。当一个客户端对象请求一个享元对象时,享元工厂角色会去检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂则提供这个已有的享元对象;否则创建一个合适的享元对象。
  • 客户端(Client)角色:该角色需要自行存储所有享元对象的外部状态。

注意:除了上面的4个角色,享元模式还会涉及符合享元角色,该角色是将一些单纯享元使用合成模式加以复合,形成复合享元对象,这些复合享元对象本身不能共享,不会出现在享元工厂中,因此也称为“不可共享的享元角色”。但可以降负荷享元对象分解成单纯的享元对象,而后者则可以共享。
享元的类图创建抽象享元角色Flyweight.java
package com.eric.结构型模式.享元模式.引例;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 抽象享元角色
 * @CreateTime 2020-12-03 11:27:05
 */
public interface Flyweight {
    //业务方法
    public abstract void operation(String  extrinsicState);
}
抽象享元角色声明一个业务方法operation(),该方法的参数书享元对象的外部状态。具体享元ConcreteFlyweight实现抽象享元Flyweight接口。
创建具体享元Concrete.java
package com.eric.结构型模式.享元模式.引例;


/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 具体享元
 * @CreateTime 2020-12-03 11:29:24
 */
public class ConcreteFlyweight implements Flyweight{
    private String intrinsicState; //内部状态
    ConcreteFlyweight(String intrinsicState){
        this.intrinsicState = intrinsicState;
    }

    @Override
    public void operation(String extrinsicState) {
        System.out.println("内部状态"+intrinsicState+"---外部状态"+extrinsicState);
    }
}
具体享元类定义了一个IntrnsicState属性,该属性用于村相互享元对象的内部状态,并通过构造函数中的参数对内部状态进行赋值。
享元工厂FlyweightFactory.java
package com.eric.结构型模式.享元模式.引例;

import java.util.HashMap;
import java.util.Map;
/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 享元工厂
 * @CreateTime 2020-12-03 11:33:03
 */
public class FlyweightFactory {
    private static Map<String,Flyweight> pool = new HashMap<String, Flyweight>();
    private FlyweightFactory(){}//私有构造方法
    public static Flyweight getFlyweight(String intrinsicState){
        Flyweight flyweight = pool.get(intrinsicState);
        if(flyweight == null){
            flyweight = new ConcreteFlyweight(intrinsicState);
            pool.put(intrinsicState,flyweight);
        }
        return flyweight;
    }
}
享元工厂使用一个静态的Map集合来存放享元对象,该集合是池容器。静态方法getFlyWeight()可以根据内部的状态值获取享元对象。因为内部状态不改变,所以可以作为主键,并根据气质从池容器中获取享元对象即可;如何池容器中无对应的享元对象,则创建一个新的享元对象并保存到池容器中。

2享元模式的应用

a.享元模式的优缺点享元模式的优点在于答复减少内存中对象的数量,降低程序内存的占用,提高性能。但是,相应付出的代价也很高。
  • 享元模式增加了系统的复杂性,需要分出外部状态和内部状态,而且内部状态具有固化特性,不应该随外部状态改变而改变,这使得程序的逻辑复杂化。
  • 享元模式将享元对象的状态外部化,而读取外部状态使得运行时间变长。
b.享元模式的使用场景使用享元模式的典型场景。
  • 系统中有大量的相似对象,这些对象耗费大量内存。
  • 细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,几对象没有特定的身份。
Java基础类库中大量使用了享元模式,如String、Integer、Boolean、Character等类都通过享元模式提供了内部的池化机制。

3享元模式的实例

利用享元模式模拟下棋的过程。定义棋子接口,规范落子方法put(),对棋子进行定位。Chesspiece.java
package com.eric.结构型模式.享元模式.例1;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 棋子接口规范
 * @CreateTime 2020-12-03 13:17:38
 */
public interface Chesspiece  {
    //落子
    void put(int x,int y);
}
ChesspieceFlyweight.java
package com.eric.结构型模式.享元模式.例1;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 棋子具体享元
 * @CreateTime 2020-12-03 13:48:48
 */
public class ChesspieceFlyweight implements Chesspiece {
    private String color;

    public ChesspieceFlyweight(String color){
        this.color = color;
    }

    @Override
    public void put(int x, int y) {
        System.out.println("在("+x+","+y+")位置放了一个"+color+"子");
    }
}
color属性是棋子的内部状态,构造函数带参数对color赋值,并实现落子put()方法;棋子工厂棋子工厂是享元工厂,负责创建和管理棋子。ChesspieceFactory.java
package com.eric.结构型模式.享元模式.例1;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 棋子工厂
 * @CreateTime 2020-12-03 13:55:23
 */
public class ChesspieceFactory {
   private static final Chesspiece WHITE = new ChesspieceFlyweight("白");
   private static final Chesspiece BLACK = new ChesspieceFlyweight("黑");

    public static Chesspiece getChesspiece(String color){
        if("白".equals(color))return WHITE;
        else if("黑".equals(color))return BLACK;
        return null;
    }
}
下棋时只需要黑白两种棋子,所以在棋子工厂ChesspieceFactory中直接创建黑白棋子对象,因此没有用Map集合来存放棋子对象。getChesspiece()方法根据颜色返回相应的棋子对象。测试类Game.java
package com.eric.结构型模式.享元模式.例1;

/**
 * @author Eric
 * @ProjectName my_design_23
 * @description 开始游戏
 * @CreateTime 2020-12-03 14:00:09
 */
public class Game {
    public static void main(String[] args) {
        Chesspiece chesspiece1 = ChesspieceFactory.getChesspiece("黑");
        chesspiece1.put(3,3);
        Chesspiece chesspiece2 = ChesspieceFactory.getChesspiece("白");
        chesspiece2.put(3,4);
        Chesspiece chesspiece3= ChesspieceFactory.getChesspiece("黑");
        chesspiece3.put(2,4);
        Chesspiece chesspiece4 = ChesspieceFactory.getChesspiece("白");
        chesspiece4.put(4,4);
    }
}
测试结果



来自为知笔记(Wiz)

标签:享元,状态,对象,模式,棋子,public
来源: https://www.cnblogs.com/zyl-0110/p/14204692.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有