1. 什么是享元模式
Flyweight模式也叫享元模式,是构造型模式之一,它通过与其他类似对象共享数据来减小内存占用。
2.享元模式的结构
3.享元模式的角色和职责
抽象享元角色:
所有具体享元类的父类,规定一些需要实现的公共接口。
具体享元角色:
抽象享元角色的具体实现类,并实现了抽象享元角色规定的方法。
享元工厂角色: 负责创建和管理享元角色。
先来个简单的例子。大体是这样的:现在要存储”a”,”b”,”c”,”d”四个字符,如果一个字符用一个对象存储,当然要4个对象,因为每个字符都不相同嘛。但是如果存储”a”,”b”,”a”,”d”四个字符,应该要几个对象就能存储,当然要3个对象就够了。现在,我们看看是如何实现的。
首先定义存储字符的类:
//MyCharacter.java
public class MyCharacter {
private char mychar;
public MyCharacter(char mychar){
this.mychar = mychar;
}
public void display(){
System.out.println(this.mychar);
}
}
如果一个字符存储在一个对象中,不区分相同的字符,那么大概是下面这样子的。
//MainClass.java
public class MainClass {
public static void main(String[] args) {
MyCharacter mychar1 = new MyCharacter('a');
MyCharacter mychar2 = new MyCharacter('b');
MyCharacter mychar3 = new MyCharacter('a');
MyCharacter mychar4 = new MyCharacter('d');
mychar1.display();
mychar2.display();
mychar3.display();
mychar4.display();
if(mychar1 == mychar3)
System.out.println("true");
else
System.out.println("false");
那么打印结果是:
a
b
a
d
false
这个,应该很好理解吧。mychar1 和 mychar2 两个都是new出来的,显示在堆上不是同一个对象。但是,他们的内容完全一样,按照我们的想法,他们应该是一样的,这样只需一份内存就可以了。
so,下面,我们创建一个工厂,专门生成MyCharacter对象,但是在生成的时候做些手脚,看代码:
//MyCharacterFactory.java
import java.util.HashMap;
import java.util.Map;
/**
* 管理 MyCharacter
*/
public class MyCharacterFactory {
private Map<Character,MyCharacter> pool;
public MyCharacterFactory(){
pool = new HashMap<Character, MyCharacter>();
}
public MyCharacter getMyCharacter(Character character){
MyCharacter mychar = pool.get(character);
if(mychar == null){
mychar = new MyCharacter(character);
pool.put(character, mychar);
}
return mychar;
}
}
应该很好理解吧,MyCharacterFactory中维护了一个容器pool,该容器对MyCharacter对象进行管理,这样,在请求MyCharacter对象的时候,如果该对象不在pool中则new一个返回,再将该新对象加到pool容器中,如果请求的对象恰好在容器中,则直接取出返回就可以了。这样的好处就是,不会有数据冗余。
现在,客户端的代码就变成这样子了:
//MainClass.java
public class MainClass {
public static void main(String[] args) {
MyCharacterFactory myfact = new MyCharacterFactory();
MyCharacter mychar1 = myfact.getMyCharacter('a');
MyCharacter mychar2 = myfact.getMyCharacter('b');
MyCharacter mychar3 = myfact.getMyCharacter('a');
MyCharacter mychar4 = myfact.getMyCharacter('d');
mychar1.display();
mychar2.display();
mychar3.display();
mychar4.display();
if(mychar1 == mychar3)
System.out.println("true");
else
System.out.println("false");
}
}
打印结果是:
a
b
a
d
true
还觉得不过瘾,我们再来个例子。上面的例子和前面的享元模式结构图相比,省略了Flyweight基类的创建,而是直接给了个具体的子类MyCharacter,下面的例子,我们完全按照上面的结构图来:
首先定义基类Person:
//Person.java
package com.zemo.wj;
public class Person {
private String name;
private int age;
private String sex;
public Person(String name, int age, String sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
定义实现子类Teacher:
//Teacher.java
package com.zemo.wj;
public class Teacher extends Person {
private String number;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Teacher(String name, int age, String sex,String number) {
super(name, age, sex);
this.number = number;
}
public Teacher() {
super();
}
}
定义创建子类的工厂,和前面例子的套路是一样一样的,都是维护一个容器对Teacher进行管理:
//TeacherFactory.java
package com.zemo.wj;
import java.util.HashMap;
import java.util.Map;
public class TeacherFactory {
private Map<String,Teacher> pool;
public TeacherFactory() {
pool = new HashMap<String,Teacher>();
}
public Teacher getTeacher(String number) {
Teacher teacher = pool.get(number);
if(teacher == null) {
teacher = new Teacher();
teacher.setNumber(number);
pool.put(number, teacher);
}
return teacher;
}
}
再看客户端的实现:
//MainClass.java
package com.zemo.wj;
public class MainClass {
public static void main(String[] args) {
TeacherFactory factory = new TeacherFactory();
Teacher teacher1 = factory.getTeacher("0102034");
Teacher teacher2 = factory.getTeacher("0102035");
Teacher teacher3 = factory.getTeacher("0102034");
Teacher teacher4 = factory.getTeacher("0102037");
System.out.println(teacher1.getNumber());
System.out.println(teacher2.getNumber());
System.out.println(teacher3.getNumber());
System.out.println(teacher4.getNumber());
if(teacher1 == teacher3) {
System.out.println("true");
} else {
System.out.println("false");
}
}
}
最后打印结果:
true