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

java设计模式之享元模式

2018-03-21 02:32 507 查看
    享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

    解决问题:在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

何时使用:
    1、系统中有大量对象。
    2、这些对象消耗大量内存。
    3、这些对象的状态大部分可以外部化。
    4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。
    5、系统不依赖于这些对象身份,这些对象是不可分辨的。

如何解决:用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。
关键代码:用 HashMap 存储这些对象。
应用实例: 
    1、JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。
     2、数据库的数据池。
    3、系统有大量相似对象。如26个英文字母的存储。
    4、需要缓冲池的场景。
JDK中的享元模式
    Integer、Lang、Byte、String等都用到了享元模式
    Integ
4000
er、Lang、Byte中的valueOf()方法用到了享元模式,String常量池就是享元模式。
享元模式UML结构图:



角色说明:
    1)抽象享元角色(Flyweight):此角色是所有的具体享元类的超类,为这些类规定出需要实现的公共接口或抽象类。那些需要外部状态(External State)的操作可以通过方法的参数传入。抽象享元的接口使得享元变得可能,但是并不强制子类实行共享,因此并非所有的享元对象都是可以共享的。
    2)具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定的接口。如果有内部状态的话,必须负责为内部状态提供存储空间。享元对象的内部状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享。有时候具体享元角色又叫做单纯具体享元角色,因为复合享元角色是由单纯具体享元角色通过复合而成的。
    3) 复合享元(UnsharableFlyweight)角色:复合享元角色所代表的对象是不可以共享的,但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。复合享元角色又称作不可共享的享元对象。这个角色一般很少使用。
    4)享元工厂(FlyweightFactoiy)角色:本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象请求一个享元对象的时候,享元工厂角色需要检查系统中是否已经有一个符合要求的享元对象,如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个新的合适的享元对象。
    5)客户端(Client)角色:本角色还需要自行存储所有享元对象的外部状态。
内部状态与外部状态
    在享元对象内部并且不会随着环境改变而改变的共享部分,可以称之为享元对象的内部状态,反之随着环境改变而改变的,不可共享的状态称之为外部状态。
实例:public class Person {

private String name;
private int age;
private String sex;

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;
}
}

/**
* 抽象享元角色
* @author Administrator
*
*/
public abstract class FlyWeight {

private String number;

public FlyWeight(String number){
super();
this.number = number;
}

public String getNumber() {
return number;
}

public void setNumber(String number) {
this.number = number;
}

public abstract void user(Person person);
}

/**
* 具体享元角色
* @author Administrator
*
*/
public class Teacher extends FlyWeight {
public Teacher(String number) {
super(number);
}

@Override
public void user(Person person) {
System.out.println("the number is:" + this.getNumber());
System.out.println("userName:" + person.getName());
System.out.println("age:" + person.getAge());
}

}

/**
* 享元工厂角色
*/
public class TeacherFactory {
private static Map<String , FlyWeight> factory = new ConcurrentHashMap<String, FlyWeight>();

public static FlyWeight createFlyWeight(String number){
FlyWeight flyWeight = factory.get(number);
if (flyWeight == null) {
flyWeight = new Teacher(number);
factory.put(number, flyWeight);
}
return flyWeight;
}

public static int objectCount(){
return factory.size();
}
}
public class MainClass {
public static void main(String[] args) {
FlyWeight flyWeight = TeacherFactory.createFlyWeight("001");
Person person = new Person();
person.setName("teacher1");
person.setAge(25);
flyWeight.user(person);

FlyWeight flyWeight2 = TeacherFactory.createFlyWeight("002");
Person person2 = new Person();
person2.setName("teacher2");
person2.setAge(26);
flyWeight2.user(person2);

FlyWeight flyWeight3 = TeacherFactory.createFlyWeight("003");
Person person3 = new Person();
person3.setName("teacher1");
person3.setAge(25);
flyWeight3.user(person3);

FlyWeight flyWeight4 = TeacherFactory.createFlyWeight("002");
Person person4 = new Person();
person4.setName("teacher4");
person4.setAge(28);
flyWeight4.user(person4);

System.out.println("对象数量:" + TeacherFactory.objectCount());
}
}优缺点:

优点:大幅度地降低内存中对象的数量,减缓堆内存压力,降低系统的内存,使效率提高。
缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而读取外部状态使得运行时间稍微变长。而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: