设计模式:享元模式

  享元模式中的享指的共享的意思,该模式以共享的方式支持某些对象的重用(特别是一些大的对象)以此节约空间。典型的是以时间换空间的做法。

例如:java语言中String类型就是使用享元模式。对于JVM来说,String对象都是共享的。如果一个系统中两个String对象所包含的字符串内容相同,jvm

实际上只创建一个String对象提供两个引用。

  享元模式一般的角色:

    享元工厂类(FlyWeight享元工厂类):管理享元对象

    抽象享元类(FlyWeight抽象类):接口或抽象类,向外界提供对象内部状态。

    具体享元类(ConcreteFlyWeight):继承自抽象享元类。为内部状态提供成员变量存储。

    非共享享元类(UnshareConcreteFlyWeight):不能被共享的一些子类。

  享元对象能作为共享的的关键是区分内部状态和外部状态。

    内部状态:可以共享。

    外部状态:不可以共享。

例子:

  描述一个围棋软件,每个棋子是一个对象(颜色,形状等)这些是可以共享的,对应内部状态。只有棋子的位置不是共享的,对应外部状态。  

/**
 * 享元类 
 */
public interface ChessFlyWeight {
   //颜色  
    void setColor(String c);
    String getColor();
    //描述位置  
    void display(Position c);
}

  

class OneChess implements ChessFlyWeight{
  //为内部状态提供成员变量存储。
    private String color;

    public OneChess(String color) {
        super();
        this.color = color;
    }

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

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

    @Override
    public void setColor(String c) {
        this.color = c;
    }
}

  外部状态位置单独设计一个类

/**
 * 外部状态UnSharedConcreteFlyWeight
 * 非共享狀態
 */
public class Position {
    private int x;
    private int y;

    public Position(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;
    }
}

  

  享元工厂类

/**
 * 享元工厂类 
 * 创建和管理享元对象
 */
public class ChessFlyWeightFactory {

    //享元池  
    private static Map<String,ChessFlyWeight> map = new HashMap<String, ChessFlyWeight>();

    public static ChessFlyWeight  getChess(String color){

        if(map.get(color)!=null){
            return map.get(color);
        }else{
            ChessFlyWeight cfw = new OneChess(color);
            map.put(color, cfw);
            return cfw;
        }

    }
}

  

public class Client {
    public static void main(String[] args) {
        ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess("黑色");
        ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess("黑色");
        System.out.println(chess1 == chess2);

        System.out.println("增加位置外部状态");
        chess1.display(new Position(1, 12));
        chess2.display(new Position(50, 60));

    }
}

  

  使用享元模式一般步骤:

    1. 抽象享元对象,内部状态采用享元类处理

    2. 外部状态(可变状态,非共享)单独抽取类处理

    3. 设计享元工厂类,采用对象池管理享元对象。

  一般使用场景是对象池,将对象缓存。极大减少内存中对象的数量相同或相似对象内存中只存一份,极大的节约资源,提高系统性能

  

 

 

 

    

posted @ 2019-01-10 21:32  小阿Q的博客  阅读(209)  评论(0编辑  收藏  举报