17 结构型模式-享元模式

1 享元模式介绍


2 享元模式原理



3 享元模式实现

抽象享元类可以是一个接口也可以是一个抽象类,作为所有享元类的公共父类, 主要作用是提高系统的可扩展性.

java 复制代码
//* 抽象享元类
public abstract class Flyweight {
	public abstract void operation(String extrinsicState);
}

具体享元类

具体享元类中要将内部状态和外部状态分开处理,内部状态作为具体享元类的成员变量,而外部状态通过注入的方式添加到具体享元类中.

java 复制代码
/**
 * 可共享的-具体享元类
 * 注意: 在具体享元类中,需要将内部状态和外部状态分开处理.
 **/
public class ConcreteFlyweight extends Flyweight{

    //内部状态 : inState作为一个成员变量,同一个享元对象的内部状态是一致的.
    private String inState;

    public ConcreteFlyweight(String inState) {
        this.inState = inState;
    }

    /**
     * 外部状态在使用的时候,通常是有外部设置,不保存在享元对象中,即使是同一个对象
     * @param state
     */
    @Override
    public void operation(String state) {

        System.out.println("=== 享元对象的内部状态: " + inState + ",外部状态: " + state );
    }
}

非共享享元类,不复用享元工厂内部状态,但是是抽象享元类的子类或实现类

java 复制代码
/**
 * 非共享的具体享元类
 **/
public class UnsharedFlyweight  extends Flyweight{

    private String inState;

    public UnsharedFlyweight(String inState) {
        this.inState = inState;
    }

    @Override
    public void operation(String state) {
        System.out.println("=== 使用不共享对象,内部状态: " + inState + ",外部状态: " + state );
    }
}

享元工厂类, 管理一个享元对象类的缓存池。它会存储享元对象之间需要传递的共有状态,比如,按照大写英文字母来作为状态标识,这种只在享元对象之间传递的方式就叫内部状态。同时,它还提供了一个通用方法getFlyweight(),主要通过内部状态标识来获取享元对象。

java 复制代码
/**
 * 享元工厂类
 * 作用: 作为存储享元对象的享元池.用户获取享元对象时先从享元池中获取,有则返回,没有创建新的返回给用户,
 * 并且在享元池中保存
 **/
public class FlyweightFactory {

    //定义一个Map集合用于存储享元对象,实现享元池
    private Map<String,Flyweight> pool = new HashMap<>();

    //实现享元对象之间的状态传递
    public FlyweightFactory() {
        //添加对应的内部状态
        pool.put("A",new ConcreteFlyweight("A"));
        pool.put("B",new ConcreteFlyweight("B"));
        pool.put("C",new ConcreteFlyweight("C"));
    }

    //根据内部状态进行查找
    public Flyweight getFlyweight(String key){
        //对象是否存在
        if(pool.containsKey(key)){
            System.out.println("=== 享元池中存在,直接复用,key : " + key);
            return pool.get(key);
        }else{
            //如果对象不存在,就创建一个添加到享元池,然后返回
            System.out.println("=== 享元池中不存在,创建并复用,key: " + key);
            Flyweight fw = new ConcreteFlyweight(key);
            pool.put(key,fw);
            return  fw;
        }
    }
}
java 复制代码
public class Client {

    public static void main(String[] args) {

        //获取工厂对象
        FlyweightFactory factory = new FlyweightFactory();

        //通过工厂对象获取共享的享元对象
        Flyweight a1 = factory.getFlyweight("A");
        a1.operation("a1ExState");

        Flyweight a2 = factory.getFlyweight("A");
        a2.operation("a2ExState");
        System.out.println(a1 == a2);

        //获取非共享的享元对象
        UnsharedFlyweight u1 = new UnsharedFlyweight("A");
        UnsharedFlyweight u2 = new UnsharedFlyweight("A");
        System.out.println(u1 == u2);
    }
}
4 享元模式应用实例


java 复制代码
/**
 * 抽象享元类: 五子棋
 **/
public abstract class GobangFlyweight {

    public abstract String getColor();

    public void display(){
        System.out.println("棋子颜色: " + this.getColor());
    }
}
java 复制代码
/**
 * 共享享元类-白色棋子
 **/
public class WriteGobang extends GobangFlyweight {


    @Override
    public String getColor() {
        return "白色";
    }
}
java 复制代码
/**
 * 共享享元类-黑色棋子
 **/
public class BlackGobang extends GobangFlyweight {


    @Override
    public String getColor() {
        return "黑色";
    }
}
java 复制代码
/**
 * 享元工厂类-生产五子棋棋子
 **/
public class GobangFactory {

    //享元池
    private static Map<String,GobangFlyweight> pool;

    //创建共享享元对象,设置对象的内部状态
    private GobangFactory() {
        pool = new HashMap<>();
        GobangFlyweight black = new BlackGobang(); //黑子
        GobangFlyweight write = new WriteGobang(); //白子

        pool.put("b",black);
        pool.put("w",write);
    }


    //获取唯一享元工厂对象的方法
    public static GobangFactory getInstance(){
       return SingletonHolder.INSTANCE;
    }

    //静态内部类
    private static class SingletonHolder{
        private static final GobangFactory INSTANCE = new GobangFactory();
    }

    //通过key获取集合中的享元对象
    public GobangFlyweight getGobang(String key){
        return pool.get(key);
    }

}
java 复制代码
public class Client {

    public static void main(String[] args) {

        GobangFactory instance = GobangFactory.getInstance();

        //获取3颗黑子
        GobangFlyweight b1 = instance.getGobang("b");
        GobangFlyweight b2 = instance.getGobang("b");
        GobangFlyweight b3 = instance.getGobang("b");
        System.out.println("判断黑子是否是同一对象: " + (b1 == b2));

        GobangFlyweight w1 = instance.getGobang("w");
        GobangFlyweight w2 = instance.getGobang("w");
        System.out.println("判断白子是否是同一对象: " + (w1 == w2));

        //显示棋子
        b1.display();
        b2.display();
        b3.display();
        w1.display();
        w2.display();
    }
}
5 享元模式总结



相关推荐
极创信息3 分钟前
信创产品认证怎么做?信创产品测试认证的主要流程
java·大数据·数据库·金融·软件工程
SamDeepThinking22 分钟前
并发量就算只有2,该上锁还得上呀
java·后端·架构
Alice-YUE33 分钟前
【js高频八股】防抖与节流
开发语言·前端·javascript·笔记·学习·ecmascript
Sam_Deep_Thinking38 分钟前
如何让订单系统和营销系统解耦
java·架构·系统架构
云泽80838 分钟前
C++11 核心特性全解:列表初始化、右值引用与移动语义实战
开发语言·c++
froginwe111 小时前
DOM 加载函数
开发语言
lzhdim1 小时前
SQL 入门 12:SQL 视图:创建、修改与可更新视图
java·大数据·服务器·数据库·sql
Hello eveybody1 小时前
介绍一下背包DP(Python)
开发语言·python·动态规划·dp·背包dp
AI进化营-智能译站1 小时前
ROS2 C++开发系列12-用多态与虚函数构建可扩展的ROS2机器人行为模块
开发语言·c++·ai·机器人
iCxhust2 小时前
微机原理实践教程(C语言篇)---A002流水灯
c语言·开发语言·单片机·嵌入式硬件·51单片机·课程设计·微机原理