您的位置:首页 > 编程语言 > Java开发

JAVA设计模式学习之Flyweight模式(1)

2008-04-12 18:53 246 查看
今天看了<<Design patterns in java>>这本书,学习了其中的Flyweight设计模式,感觉其是一种非常优秀,且非常有用的设计模式.于是想结合自己在书上所学的与在网上所见的将此种设计模式作一下探讨.

Flyweight设计模式也称为享元模式,它的目的在于避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类).

在进行面向对象设计与面向对象编程时一切均是以对象作为核心的.但是有时真正使用起来,可能同一类型对象的数量会相当庞大,且总有一些对象中会有一些属性的值是相同的.如在每一个对象中均定义这些属性,会使得值相同的属性得不到共享,这样由于对象数相当庞大,可能会浪费很大的内存.
Flyweight设计模式的精髓就在于"求同存异",将各对象中可能会有大量值相同重复的属性抽取出来,封装到一个对象当中,只保留一个版本,这样就避免了重复,达到了节约内存的功能.

下面我以学生课程成绩为例来说明Flyweigth设计模式的应用.
假设我们在实际中有这样的需求,要求构造一个学生一门课程成绩这样的类,可以这样:
首先设计类StuScore,它表示一个学生一门课程的成绩,包含以下四个属性
l stuNum学生学号
l stuName学生姓名
l course课程名
l score该名学生此课程的成绩
按照我们最一般的做法,我们会把StuScore类直接设计成包含这四个属性,然后再针对每一个属性定义一个get方法,这样就可以完成所应该达到的功能.
注意如果采用此种方法,会存在一些问题,请看:
  假设有一名叫张三的学生,他在整个大学中修了一百多门课程,那么需要为张三和他的这一百多门课程构造一百多个类.但我们可以发现,张三他的名字与学号在这一百多个类中却全都是相同的,我们没有把这些相同的内容进行共享,而是这一百多个类中都保留了相同的值,于是这就造成了相当大的内存资源浪费.

下面我采用Flyweight设计模式来解决这个问题,以达到节约内存与资源的效果..
先改进StuScore类的结构,将StuScore类中可以大量共享与重叠的stuNum与stuName字段提取出来构造成一个新的类Student,然后分别提供此两个属性的get方法.
由于可能会存在许多个学生,所以可以把它们放在一个Flyweight池中,其中可以保存所有的学生的信息,于是在此地方可以利用工厂模式,创建StudentFactory并且在工厂中建一个hashtable来维护Flyweight池,即维护所有学生信息.

学生成绩类StuScore.java代码如下:
package org.xqq.flyweight;

public class StuScore {
private Student student;//Student类型
private String course;//课程名
private int score;//课程分数

public StuScore(String stuNum,String course,int score)
{
this.course=course;
this.score=score;
//从工厂中通过学号获得Student实例
this.student=StudentFactory.getStudent(stuNum);
}
//得到课程名
public String getCourse() {
return course;
}
//得到课程成绩
public int getScore() {
return score;
}
//得到学生姓名
public String getStuName() {
return student.getStuName();
}
//得到学生学号
public String getStuNum(){
return student.getStuNum();
}
}
学生类Student.java代码如下:
package org.xqq.flyweight;
public class Student {
private String stuName;//学生姓名
private String stuNum;//学生学号
//get方法
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getStuNum() {
return stuNum;
}
public void setStuNum(String stuNum) {
this.stuNum = stuNum;
}
//构造函数
public Student(String stuName, String stuNum) {
super();
this.stuName = stuName;
this.stuNum = stuNum;
}
}

工厂类StudentFactory.java代码如下:
package org.xqq.flyweight;

import java.util.Hashtable;

public class StudentFactory {
//hashtable用于维护Student对象
private static Hashtable stuTable=new Hashtable();
//通过静态代码创建所有学生的信息,保存到工厂的hashtable中
static
{
stuTable.put("AP0501",
new Student("AP0501","张三"));
stuTable.put("AP0502",
new Student("AP0502","李四"));
stuTable.put("AP0503",
new Student("AP0503","王五"));
}
//从工厂类中取得特定的学生信息
public static Student getStudent(String stuNum)
{
Student student=(Student) stuTable.get(stuNum);
return student;
}
下面对所写的Flyweight模式进行测试,编写测试类代码StudentTest.java:
package org.xqq.flyweight;

public class StudentTest {
public static void main(String[] args)
{
StuScore score1=new StuScore("AP0501","高等数学",85);
StuScore score2=new StuScore("AP0501","大学英语",89);
StuScore score3=new StuScore("AP0501","java语言",95);

System.out.println("学号: "+score1.getStuNum()
+",姓名:"+score1.getStuName()
+",科目:"+score1.getCourse()
+",成绩: "+score1.getScore());

System.out.println("学号: "+score2.getStuNum()
+",姓名:"+score2.getStuName()
+",科目:"+score2.getCourse()
+",成绩: "+score2.getScore());

System.out.println("学号: "+score3.getStuNum()
+",姓名:"+score3.getStuName()
+",科目:"+score3.getCourse()
+",成绩: "+score3.getScore());
}
}

输出结果,如下所示:
学号: 张三,姓名:AP0501,科目:高等数学,成绩: 85
学号: 张三,姓名:AP0501,科目:大学英语,成绩: 89
学号: 张三,姓名:AP0501,科目:java语言,成绩: 95
通过结果可以看到在运用Flyweight设计模式之后,我们虽然在测试类中新建了学生张三的三门课程成绩信息,即新建了三个StuScore对象,但学生张三的学号与姓名却只在工厂类中保留一份,于是达到了Flyweight设计模式共享元类,避免大量拥有相同内容的小类的开销,.节约内存与资源的效果.

对于Flyweight设计模式<<Design patterns in java>>还有更精彩的部分,我将在本文的下期进行介绍.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: