1.享元模式
运用共享技术有效地支持大量细粒度的对象。
2.基础代码
(1)Flyweight类
package designmode.flyweight;
public abstract class Flyweight {
public abstract void Operation(int extrinsicstate);
}
(2)ConcreteFlyweight
package designmode.flyweight;
public class ConcreteFlyweight extends Flyweight{
@Override
public void Operation(int extrinsicstate) {
System.out.println("具体Flyeight:"+extrinsicstate);
}
}
(3)UnsharedFlyweight
package designmode.flyweight;
public class UnsharedConcreteFlyweight extends Flyweight{
@Override
public void Operation(int extrinsicstate) {
System.out.println("不共享的具体Flyweight:"+extrinsicstate);
}
}
(4)FlyweightFactory
package designmode.flyweight;
import com.sun.webkit.network.data.Handler;
import java.util.Hashtable;
public class FlyweightFactory {
private Hashtable<String,Flyweight> flyweightHashtable= new Hashtable<>();
public FlyweightFactory(){
//初始化时,先生成三个实例
flyweightHashtable.put("X",new ConcreteFlyweight());
flyweightHashtable.put("Y",new ConcreteFlyweight());
flyweightHashtable.put("Z",new ConcreteFlyweight());
}
public Flyweight GetFlyweight(String key){
//根据客户端请求,获得以已经生成的实例
return (Flyweight) flyweightHashtable.get(key);
}
}
(5)客户端
package designmode.flyweight;
public class Client {
public static void main(String[] args) {
int extrinsicstate=22; //代码外部状态
FlyweightFactory f=new FlyweightFactory();
Flyweight fx=f.GetFlyweight("X");
fx.Operation(--extrinsicstate);
Flyweight fy=f.GetFlyweight("Y");
fy.Operation(--extrinsicstate);
Flyweight fz=f.GetFlyweight("Z");
fz.Operation(--extrinsicstate);
UnsharedConcreteFlyweight uf=new UnsharedConcreteFlyweight() ;
uf.Operation(--extrinsiccstate);
}
}
测试结果
具体Flyeight:21
具体Flyeight:20
具体Flyeight:19
不共享的具体Flyweight:18
Process finished with exit code 0
PS: FlyweiFactory不一定事先生成对象实例,而是在需要的时候,先判断是否对象为null,不为空就创建实例。
UnsharedConcreteFlyweight用于应对不需要共享对象的问题。
3.内部状态与外部状态
在享元对象内部并且不会随环境改变而改变的共享部分,可以称为是享元对象的内部状态。而随环境改变而改变的,不可以共享的状态就是外部状态了
- 享元模式可以避免大量非常相似类的开销。
- 在程序设计中有时需要生成大量细粒度的类实例来标识数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够大幅度减少需要实例化的类的数量。
- 如果能把那些参数移到类实例的外边,在方法调用时将他们传递过来,就可以通过共享大幅度减少单个实例的数目。
- 内部状态存储与ConcreteFlyweight对象之中,而外部对象则应该考虑由客户端对象存储或者计算。当调用Flyweight对象的操作时,将该状态传递给它。
4.应用场景
-
如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用
-
还有就是对象的大多数状态可以是外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。
优点
-
使用享元模式后,会有共享对象,实例总数会大大减少,如果共享的对象越多,存储节约也就越多,节约量随着共享状态的增多而增大。
缺点
使用享元模式需要维护一个记录了系统已有的所有享元的列表,而这本身需要耗费资源。另外享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,使得程序的逻辑复杂化