享元模式

159 阅读2分钟

享元模式定义

重用现有的类,通过缓存的构造理念,将状态相同,复用性多且状态变化小的对象存储于缓存中(享元模式在存储于hashmap中,且存储map中的对象为类的"模板",并不是全部类的实例),适用于有着大量的对象实例时使用。

享元模式实现

public interface FlyweightInterface {

    void same();
}

抽象享元类 需要重用类中使用到的的方法。

public class SameMode implements FaceInterface{

    private String name;
    private int price;
    private int age;

    public SameMode(String name) {
        this.name = name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public void food() {
        System.out.println("SameMode{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", age=" + age +
                '}');
    }
}

共享享元类,即需要重用的类。实现抽象享元类实现其方法。

public class ModeFactory {

    public static final HashMap<String, FaceInterface> maps = new HashMap<>();

    public static SameMode getSame(String name) {
        SameMode mode = (SameMode)maps.get(name);
        if (mode == null) {
            mode = new SameMode(name);
            maps.put(name, mode);
            System.out.println("create mode food" + name);
        }
        return mode;
    }
}

享元类存储于HashMap以唯一标识为Key存储类的"模板",如果存在即获取,失败则创建。相信看到这里,就能联想到后面的线程安全问题了。

public class FlyweightTest {
    private static final String[] strings = new String[] {"chicken", "beef", "pig"};
    private static Random random = new Random();

    public static void main(String[] args) {

        for (int i = 0; i <20 ; i++) {
            SameMode s = ModeFactory.getSame(strings[getRandom()]);
            s.setAge(getandom1());
            s.setPrice(getandom1());
            s.food();
        }
    }

    private static int getRandom() {
        return random.nextInt(3);
    }

    private static int getandom1() {
        return random.nextInt(100);
    }
}

测试类 创建多个根据享元模式创建的对象

// 测试结果
create mode foodbeef
SameMode{name='beef', price=89, age=77}
SameMode{name='beef', price=53, age=48}
create mode foodchicken
SameMode{name='chicken', price=45, age=5}
SameMode{name='beef', price=38, age=80}
SameMode{name='beef', price=80, age=19}
create mode foodpig
SameMode{name='pig', price=4, age=98}
SameMode{name='chicken', price=43, age=69}
SameMode{name='beef', price=7, age=56}
SameMode{name='beef', price=49, age=11}
SameMode{name='beef', price=12, age=35}
SameMode{name='beef', price=29, age=7}
SameMode{name='chicken', price=72, age=34}
SameMode{name='chicken', price=3, age=26}
SameMode{name='beef', price=8, age=95}
SameMode{name='pig', price=64, age=77}
SameMode{name='chicken', price=53, age=51}
SameMode{name='pig', price=47, age=18}
SameMode{name='pig', price=82, age=71}
SameMode{name='pig', price=43, age=17}
SameMode{name='chicken', price=13, age=38}

Process finished with exit code 0

小结

  • 优点:如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建,减少了类的重复创建减少了内存的使用
  • 缺点:实例存于线程共享的堆中,因此有着线程安全问题,在多线程的环境下需要对应的同步块或者独占锁实现。

详细源码下载地址: github.com/Liyinzuo/De…

以上便是享元模式介绍,如果那里错误或者不足地方欢迎指正。