什么是享元模式
享——共享,元——元数据,可以理解为对象,即共享一组对象,享元模式能实现一组对象的共享,就和我们熟悉的数据库连接池一样。
享元模式的角色
Flyweight:抽象享元类,规定外部状态的设定方法以及具体享元类的共有方法
ConcreteFlyweight:具体享元类,实现具体的共享对象,可以包括内部状态和外部状态
UnsharedConcreteFlyweight:非共享具体享元类,享元模式并没有严格要求对象一定要共享,对于非共享对象,每次使用时由客户端自己实例化
FlyweightFactory: 享元工厂类,根据要求返回享元对象
内部状态:不会发生变化的部分,即共享的状态
外部状态:会发生变化的部分,由客户端决定
下面举个例子,有A、B两个字母,可以设定字母的大小:
Fyweight:
public interface Fyweight {
void operator(int Font);
void display();
}
ConcreteFyweightA:
public class ConcreteFyweightA implements Fyweight{
private String Character;
private int Font;
public ConcreteFyweightA(){
this.Character="A";
}
public void operator(int Font){
this.Font=Font;
}
@Override
public void display() {
System.out.println("字符A的大小为"+Font);
}
}
ConcreteFyweightB:
public class ConcreteFyweightB implements Fyweight{
private String Character;
private int Font;
public ConcreteFyweightB(){
this.Character="B";
}
public void operator(int Font){
this.Font=Font;
}
@Override
public void display() {
System.out.println("字符B的大小为"+Font);
}
}
FyweightFactory:
import java.util.Hashtable;
public class FyweightFactory {
Hashtable<String,Fyweight> hashtable=new Hashtable<String,Fyweight>();
public FyweightFactory(){
hashtable.put("A",new ConcreteFyweightA());
hashtable.put("B",new ConcreteFyweightB());
}
public Fyweight getCharacter(String Cha){
if (Cha.equals("A"))
return hashtable.get("A");
else if(Cha.equals("B"))
return hashtable.get("B");
return null;
}
}
main:
public class mian {
public static void main(String[] args){
FyweightFactory fa=new FyweightFactory();
Fyweight A=fa.getCharacter("A");
A.operator(1);
A.display();
Fyweight B=fa.getCharacter("B");
B.operator(10);
B.display();
Fyweight C=fa.getCharacter("B");
C.operator(100);
C.display();
}
}
执行结果:
上述例子中,Character属性就是内部状态,Font为外部状态,Fyweight接口需要提供外部状态的操作方法
享元模式的一点思考
享元模式实现了一组对象的共享,节省了内存,平常实现享元模式时需要注意线程安全问题,拿上面的例子来说,只有一个字符A,多线程多进程情况下有可能会发生改值问题,通过享元模式,我们能实现对象的统一管理,减少客户端出错的可能性,提高系统的性能,例如熟悉的数据库连接池,使用数据库连接池,我们就不会担心自己的数据库连接是否关闭等问题,数据库连接的复用也能减少系统的开销。