美文网首页设计模式学习小结
设计模式小结-享元模式

设计模式小结-享元模式

作者: r09er | 来源:发表于2017-12-28 21:10 被阅读7次

    享元模式概述

    当一个软件系统在运行时产生的对象数量太多,将导致运行代价过高,带来系统性能下降等问题。例如在一个文本字符串中存在很多重复的字符,如果每一个字符都用一个单独的对象来表示,将会占用较多的内存空间,那么我们如何去避免系统中出现大量相同或相似的对象,同时又不影响客户端程序通过面向对象的方式对这些对象进行操作?享元模式正为解决这一类问题而诞生。

    示例

    在围棋中,有黑白两种颜色的棋子,相同颜色的旗子除了位置不同,其他属性都是相同的,使用享元模式描述

    UML图

    示例解析

    结合了简单工厂模式的使用,旗子由简单工厂生成,棋子的颜色和坐标由客户端指定.

    示例代码

    工厂方法

    class IgoChessmanFactory {
    private static IgoChessmanFactory instance = new IgoChessmanFactory();
    private static Hashtable ht; //使用Hashtable来存储享元对象,充当享元池
    private IgoChessmanFactory() {
    ht = new Hashtable();
    IgoChessman black,white;
    black = new BlackIgoChessman();
    ht.put("b",black);
    white = new WhiteIgoChessman();
    ht.put("w",white);
    }
    //返回享元工厂类的唯一实例
    public static IgoChessmanFactory getInstance() {
    return instance;
    }
    //通过key来获取存储在Hashtable中的享元对象
    public static IgoChessman getIgoChessman(String color) {
    return (IgoChessman)ht.get(color);
    }
    }
    

    坐标类:外部状态类

    class Coordinates {
    private int x;
    private int y;
    public Coordinates(int x,int y) {
    this.x = x;
    this.y = y;
    }
    public int getX() {
    return this.x;
    }
    public void setX(int x) {
    this.x = x;
    }
    public int getY() {
    return this.y;
    }
    public void setY(int y) {
    this.y = y;
    }
    }
    

    围棋棋子类:抽象享元类

    abstract class IgoChessman {
    public abstract String getColor();
    public void display(Coordinates coord){
    System.out.println("棋子颜色:" + this.getColor() + ",棋子位置:" + coord.getX() + "," + coord.getY() );
    }
    }
    

    客户端调用

    class Client {
    public static void main(String args[]) {
    IgoChessman black1,black2,black3,white1,white2;
    IgoChessmanFactory factory;
    //获取享元工厂对象
    factory = IgoChessmanFactory.getInstance();
    //通过享元工厂获取三颗黑子
    black1 = factory.getIgoChessman("b");
    black2 = factory.getIgoChessman("b");
    black3 = factory.getIgoChessman("b");
    System.out.println("判断两颗黑子是否相同:" + (black1==black2));
    //通过享元工厂获取两颗白子
    white1 = factory.getIgoChessman("w");
    white2 = factory.getIgoChessman("w");
    System.out.println("判断两颗白子是否相同:" + (white1==white2));
    //显示棋子,同时设置棋子的坐标位置
    black1.display(new Coordinates(1,2));
    black2.display(new Coordinates(3,4));
    black3.display(new Coordinates(1,3));
    white1.display(new Coordinates(2,5));
    white2.display(new Coordinates(2,4));
    }
    }
    

    输出结果

    判断两颗黑子是否相同:true
    判断两颗白子是否相同:true
    棋子颜色:黑色,棋子位置:1,2
    棋子颜色:黑色,棋子位置:3,4
    棋子颜色:黑色,棋子位置:1,3
    棋子颜色:白色,棋子位置:2,5
    棋子颜色:白色,棋子位置:2,4
    

    外观模式优缺点

    优点

    • 1.可以极大减少内存中对象的数量,使得相同或相似对象在内存中只保存一份,从而可以节约系统资源,提高系统性能。
    • 2.享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。

    缺点

    • 1.享元模式使得系统变得复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化。
    • 2.为了使对象可以共享,享元模式需要将享元对象的部分状态外部化,而读取外部状态将使得运行时间变长。

    适用场景

    • 1.一个系统有大量相同或者相似的对象,造成内存的大量耗费。
    • 2.对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
    • 3.在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式。

    相关文章

      网友评论

        本文标题:设计模式小结-享元模式

        本文链接:https://www.haomeiwen.com/subject/rucepxtx.html