Java设计模式----享元模式

场景

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

核心

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

享元模式实现

  • FlyweightFactory享元工厂类
    创建并管理享元对象,享元池一般设计成键值对
  • Flyweight抽象享元类
    通常是一个接口或抽象类,声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态
  • ConcreteFlyweight具体享元类
    为内部状态提供成员变量进行储存
  • UnsharedConcreteFlyweight非共享享元类
    不能被共享的子类可以设计为非共享享元类


    Java设计模式----享元模式_第1张图片
    享元模式
package flyweight;

// 以围棋为例
// Flyweight
public interface Chess {
    String getColor();
    void display(Coordinate c);
}

// ConcreteFlyweight
class ConcreteChess implements Chess{
    private String color;

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

    public String getColor() {
        return color;
    }

    public void display(Coordinate c) {
        System.out.println("颜色:"+color);
        System.out.println("位置:("+c.getX()+","+c.getY()+")");
    }
}
// UnsharedConcreteFlyweight
public class Coordinate{
    private int x,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 flyweight;

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

// FlyweightFactory
public class ChessFactory {
    private static Map map = new HashMap();

    public static Chess getChess(String color){
        if (map.get(color) != null){
            return map.get(color);
        }else{
            Chess chess = new ConcreteChess(color);
            map.put(color,chess);
            return chess;
        }
    }
}
package flyweight;

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

        System.out.println("=====增加外部状态=====");

        chess.display(new Coordinate(10,10));
        chess1.display(new Coordinate(20,20));
    }
}

输出:
flyweight.ConcreteChess@4edf9252
flyweight.ConcreteChess@4edf9252
=====增加外部状态=====
颜色:黑色
位置:(10,10)
颜色:黑色
位置:(20,20)

享元模式开发中应用的场景:

  • 享元模式由于其共享的特性,可以在任何"池"中操作,比如线程池、数据库连接池。
  • String类的设计也是享元模式

优点

  • 极大减少内存中对象的数量
  • 相同或相似对象内存中只存一份,极大节约资源,提高系统性能
  • 外部状态相对独立,不影响内部状态

缺点

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

何时使用

如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。

你可能感兴趣的:(Java设计模式----享元模式)