享元模式
在享元模式中可以共享的相同内容称为 内部状态(Intrinsic State),而那些需要外部环境来设置的不能共享的内容称为 外部状态(Extrinsic State),
其中外部状态和内部状态是相互独立的,外部状态的变化不会引起内部状态的变化。由于区分了内部状态和外部状态,因此可以通过设置不同的外部状态使得相同的对象可以具有一些不同的特征,而相同的内部状态是可以共享的。
也就是说,享元模式的本质是分离与共享 : 分离变与不变,并且共享不变。把一个对象的状态分成内部状态和外部状态,内部状态即是不变的,外部状态是变化的;然后通过共享不变的部分,达到减少对象数量并节约内存的目的。
享元模式是对象池的一种实现。类似于线程池,线程池可以避免不停的创建和销毁多个对象,消耗性能。享元模式也是为了减少内存的使用,避免出现大量重复的创建销毁对象的场景。
注意事项: 1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。 2、这些类必须有一个工厂对象加以控制。
代码:
public interface FlyWeight { public void operate(String status); }
public class FlyWeightImpl implements FlyWeight { //内部状态不可改,通过构造方法传入 private String inner; public FlyWeightImpl(String inner) { this.inner = inner; } //外部状态可修改 @Override public void operate(String outer) { System.out.println("inner: " + inner + ", outer: " + outer); } }
// 类似线程池,有则从map中取出,没有则创建一个对象放到map中 public class FlyWeightFactory { Map<String, FlyWeight> map = new HashMap<>(); public FlyWeight factory(String inner) { FlyWeight fly = map.get(inner); if(fly == null) { fly = new FlyWeightImpl(inner); map.put(inner, fly); } return fly; } }
测试代码:
public class TestDemo { public static void main(String[] args) { FlyWeightFactory factory = new FlyWeightFactory(); FlyWeight f1 = factory.factory("a"); f1.operate("first"); FlyWeight f2 = factory.factory("b"); f2.operate("second"); FlyWeight f3 = factory.factory("a"); f3.operate("third"); // f1 和 f3是同一个对象 System.out.println(f1 == f3); } }
结果:
这里f3拿到的是f1的对象,且内部状态相同,外部状态不同。