DesignPattern-享元模式

享元模式:String常量池,数据库连接池,缓冲池等等都是享元模式的应用。

每次创建字符创对象时候,都需要创建一个新的字符串对象的话,内存开销很大,所以如果第一次创建了字符串对象hunter,下次在创建相同的字符串hunter时,只是把它的引用再次指向hunter,这样就实现了hunter字符串内内存中的共享。

角色:
Flyweight:抽象享元类,所有具体享元类的超类or接口,
ConcreteFlyweight:具体享元类,指定内部状态,为内部状态增加存储空间
UnsharedConcreteFlywight: 非共享具体享元类。支出那些不需要共享的Flyweight子类
FlyweightFactory:享元工厂类,用来创建并管理Flyweight对象,它主要用来确保合理地共享Flyweight,当用户请求一个Flyweight时,工厂会提供一个已经创建的对象or新建一个(如果不存在)

代码实现:
Flyweight

public abstract class Flyweight {//内部状态public String intrinsic;//外部状态protected final String extrinsic;//要求享元角色必须接受外部状态public Flyweight(String extrinsic) {this.extrinsic = extrinsic;}//定义业务操作public abstract void operate(int extrinsic);public String getIntrinsic() {return intrinsic;}public void setIntrinsic(String intrinsic) {this.intrinsic = intrinsic;}}

ConcreteFlywight

public class ConcreteFlyweight extends Flyweight {//接受外部状态public ConcreteFlyweight(String extrinsic) {super(extrinsic);}//根据外部状态进行逻辑处理@Overridepublic void operate(int extrinsic) {System.out.println("具体Flyweight:" + extrinsic);}}

UnsharedConcreteFlyweight

public class UnsharedConcreteFlyweight extends Flyweight {public UnsharedConcreteFlyweight(String extrinsic) {super(extrinsic);}@Overridepublic void operate(int extrinsic) {System.out.println("不共享的具体Flyweight:" + extrinsic);}}

FlyweightFactory

public class FlyweightFactory {//定义一个池容器private static HashMap<String, Flyweight> pool = new HashMap<>();//享元工厂public static Flyweight getFlyweight(String extrinsic) {Flyweight flyweight = null;if(pool.containsKey(extrinsic)) {    //池中有该对象flyweight = pool.get(extrinsic);System.out.print("已有 " + extrinsic + " 直接从池中取---->");} else {//根据外部状态创建享元对象flyweight = new ConcreteFlyweight(extrinsic);//放入池中pool.put(extrinsic, flyweight);System.out.print("创建 " + extrinsic + " 并从池中取出---->");}return flyweight;}
}

测试程序:

public class Client {public static void main(String[] args) {int extrinsic = 22;Flyweight flyweightX = FlyweightFactory.getFlyweight("X");flyweightX.operate(++ extrinsic);Flyweight flyweightY = FlyweightFactory.getFlyweight("Y");flyweightY.operate(++ extrinsic);Flyweight flyweightZ = FlyweightFactory.getFlyweight("Z");flyweightZ.operate(++ extrinsic);Flyweight flyweightReX = FlyweightFactory.getFlyweight("X");flyweightReX.operate(++ extrinsic);Flyweight unsharedFlyweight = new UnsharedConcreteFlyweight("X");unsharedFlyweight.operate(++ extrinsic);}}

第一次创建X、Y、Z时,都是先创建再从池中取出,而第二次创建X时,因为池中已经存在了,所以直接从池中取出

应用场景:
系统中存在大量相似对象
需要缓冲池的场景 比如:String常量池,数据库连接池

方法:
用唯一标识码判断,如果在内存中,则返回这个唯一标识码所标识的对象,用HashMap/HashTable存储

优点:
大大减少了对象的创建,降低了程序内存的占用,提高效率
缺点:
提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化性。不应该随着内部状态的改变而改变。