设计模式——11.享元模式

享元:享就是共享,元就是数据。

场景:
– 内存属于稀缺资源,不要随便浪费。如果有很多个完全相同或相似的 对象,我们可以通过享元模式,节省内存。

核心:
– 享元模式以共享的方式高效地支持大量细粒度对象的重用。
– 享元对象能做到共享的关键是区分了内部状态和外部状态。
• 内部状态:可以共享,不会随环境变化而改变
• 外部状态:不可以共享,会随环境变化而改变

案例
围棋中每一个黑棋子,每一个白棋子,都对应java世界一个对象。就会有黑子有181个对象,白子有180个对象与之对应。每个棋子有颜色,大小,形状,位置属性。
如果使用享元模式,将共享的数据抽离,每一个黑棋子,颜色,大小,形状都一样。不共享的数据抽离,每一个黑棋子的位置。这样361个棋子就只需要建立2个对象!黑棋子,白棋子!然后将不共享的数据抽出为一个类坐标,通过set方法指定给黑棋子或者白棋子。
在这里插入图片描述

享元模式实现:
– FlyWeight抽象享元类
• 通常是一个接口或抽象类,声明公共方法,这些方法可以向外界提供对象 的内部状态,设置外部状态。
– ConcreteFlyWeight具体享元类
• 为内部状态提供成员变量进行存储
– UnsharedConcreteFlyWeight非共享享元类
• 不能被共享的子类可以设计为非共享享元类
– FlyweightFactory享元工厂类
• 创建并管理享元对象,享元池一般设计成键值对 (保证单例!)

代码实现:
抽象享元类和具体享元类

package com.bjsxt.flyweight;

/**
 * 抽象享元类
 * 通常是一个接口或抽象类,声明公共方法,这些方法可以向外界提供对象 的内部状态,
 * 设置外部状态。
 */
public interface ChessFlyWeight {
    // 内部状态 颜色获取
    String getColor();
    // 外部状态 位置设置
    void display(Coordinate c);
}
class ConcreteChess implements ChessFlyWeight{
    // 内部状态 颜色
    private String color;
    // 构造器设置
    public ConcreteChess(String color) {
        this.color = color;
    }

    @Override
    public String getColor() {
        return this.color;
    }

    @Override
    public void display(Coordinate c) {
        System.out.println("棋子颜色:"+this.color+",位置:"+c.getX()+","+c.getY());
    }
}

不共享数据类

package com.bjsxt.flyweight;

public class Coordinate {
    private int x;
    private int y;

    @Override
    public String toString() {
        return "Coordinate{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }

    public Coordinate(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

享元工厂类

package com.bjsxt.flyweight;

import java.util.HashMap;
import java.util.Map;

public class ChessFlyWeightFactory {
    private static Map<String,ChessFlyWeight> map = new HashMap<>();

    public static ChessFlyWeight getChess(String color){
        if(map.get(color)!=null){
            return map.get(color);
        }else {
            ChessFlyWeight c = new ConcreteChess(color);
            map.put(color,c);
            return c;
        }
    }
}

调用方

package com.bjsxt.flyweight;

public class Client {
    public static void main(String[] args) {
        ChessFlyWeight black = ChessFlyWeightFactory.getChess("black");
        ChessFlyWeight black1 = ChessFlyWeightFactory.getChess("black");
        System.out.println(black==black1);

        Coordinate pos1 = new Coordinate(1, 1);
        Coordinate pos2 = new Coordinate(-1, -1);

        black.display(pos1);
        black.display(pos2);
    }
}

uml图
在这里插入图片描述
运行结果:
在这里插入图片描述
享元模式开发中应用的场景:
– 享元模式由于其共享的特性,可以在任何“池”中操作, 比如:线程池、数据库连接池。
– String类的设计也是享元模式

优点
– 极大减少内存中对象的数量 (361 -> 2)
– 相同或相似对象内存中只存一份,极大的节约资源,提高系统性能
– 外部状态相对独立,不影响内部状态 (Coordinate)

缺点
– 模式较复杂,使程序逻辑复杂化
– 为了节省内存,共享了内部状态,分离出外部状态,而读取外部状态 使运行时间变长。用时间换取了空间。

结构型模式总结
代理模式 为真实对象提供一个代理,从而控制对真实对象的访问 (明星唱歌)
适配模式 使原本由于接口不兼容不能一起工作的类可以一起工作(笔记本电脑usb接口 ps2键盘)
桥接模式 处理多层继承结构,处理多维度变化的场景,将各个维度设计成独立的继 承结构,使各个维度可以独立的扩展在抽象层建立关联。 (电脑品牌,种类)
组合模式 将对象组合成树状结构以表示”部分和整体”层次结构,使得客户可以统一 的调用叶子对象和容器对象 (文件夹杀毒)
装饰模式 动态地给一个对象添加额外的功能,比继承灵活 外观模式 为子系统提供统一的调用接口,使得子系统更加容易使用 (汽车与超级汽车)
享元模式 运用共享技术有效的实现管理大量细粒度对象,节省内存,提高效率(围棋棋子与位置)
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值