胖虎白话学习设计模式之享元设计模式(FlyWeight)
记录胖虎学习设计模式过程,不许勿喷,转载请注明出处!
http://blog.csdn.net/ljphhj
1.存在问题
开发中我们经常会遇到一种情况,就是“同一个对象是要被多个地方代码所共享访问”
譬如:我们网上买书时,每个订单项中包含的书籍可能别人也会买,如果所有人买这本书籍的时候,都要new出一个这个book对象的话,那么网站运行一段时间 之后就可能要GG了,所以相同的对象应该要能够实现共享.(这个例子,个人一直感觉不是很形象!如果网友有啥好的例子,方便的话留个言!)
一种模式的出现肯定是有它所解决的问题,那么看下不使用”享元模式”之前会有什么问题:
1.由于使用大量的对象,造成很大的内存浪费。(主要问题)
(PS:有知道更多的问题,希望可以给我留言哈!)
那么引入解决方法:享元设计模式
2.享元设计模式(FlyWeight)
享元设计模式概述:它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
享元设计模式定义:运用共享技术有效的支持大量细粒度的对象(百度文库的定义)[ps:通俗点就是有效地使用那些被大量使用的对象吧!]
在享元设计模式中的各个角色有:
抽象享元角色(接口):为具体享元角色规定了必须实现的方法,而外蕴状态就是以参数的形式通过此方法传入(在Java中可以由抽象类、接口来担当)
具体享元角色(实现):实现抽象角色规定的方法。如果存在内蕴状态,就负责为内蕴状态提供存储空间。
享元工厂角色:负责创建和管理享元角色。要想达到共享的目的,这个角色的实现是关键!(一般设置成单例的)
客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外蕴状态。
UML图讲述享元设计模式要点:
UML图对应代码:
这样设计后,客户类便不可以自动去new享元对象,这样就可以确保多个客户是共享同一个对象!
图2:
所以证明存在的字符串“abc”对应的字符串对象只有一个,没有多个!
享元对象的属性必须是不可变的,我们可以将这些不可变的部分提取出来构成一个享元类(interface->concreteclass)
为了能确保享元对象能够被共享,我们还必须提供一个用于创建和查找享元对象的“享元工厂类”,并且保证客户类只能使用该类来创建享元对象
把享元类设置成该类的内部类可以保证享元类只能被享元工厂类访问,这样我们就可以保证客户类只能通过这个享元工厂类对大量使用的对象进行共享访问了.
记录胖虎学习设计模式过程,不许勿喷,转载请注明出处!
http://blog.csdn.net/ljphhj
1.存在问题
开发中我们经常会遇到一种情况,就是“同一个对象是要被多个地方代码所共享访问”
譬如:我们网上买书时,每个订单项中包含的书籍可能别人也会买,如果所有人买这本书籍的时候,都要new出一个这个book对象的话,那么网站运行一段时间 之后就可能要GG了,所以相同的对象应该要能够实现共享.(这个例子,个人一直感觉不是很形象!如果网友有啥好的例子,方便的话留个言!)
一种模式的出现肯定是有它所解决的问题,那么看下不使用”享元模式”之前会有什么问题:
1.由于使用大量的对象,造成很大的内存浪费。(主要问题)
(PS:有知道更多的问题,希望可以给我留言哈!)
那么引入解决方法:享元设计模式
2.享元设计模式(FlyWeight)
享元设计模式概述:它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
享元设计模式定义:运用共享技术有效的支持大量细粒度的对象(百度文库的定义)[ps:通俗点就是有效地使用那些被大量使用的对象吧!]
在享元设计模式中的各个角色有:
抽象享元角色(接口):为具体享元角色规定了必须实现的方法,而外蕴状态就是以参数的形式通过此方法传入(在Java中可以由抽象类、接口来担当)
具体享元角色(实现):实现抽象角色规定的方法。如果存在内蕴状态,就负责为内蕴状态提供存储空间。
享元工厂角色:负责创建和管理享元角色。要想达到共享的目的,这个角色的实现是关键!(一般设置成单例的)
客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外蕴状态。
UML图讲述享元设计模式要点:
图1:
UML图对应代码:
package cn.xym.test;
import java.util.HashMap;
import java.util.Map;
/**
* 为了不让外部实例化FlyWeight对象
接口类(baseBook)和实现类(Book)全部弄成工厂类(FlyWeightFactory)的内部类
*
* @author 胖虎
*/
/**
相当于“享元工厂角色”
*/
public class FlyWeightFactory {
private static FlyWeightFactory factory = null;
private static Object mylock = FlyWeightFactory.class;
private static Map books = new HashMap();
/**
* 添加几本会被大量使用的FlyWeight对象
*/
static{
factory = new FlyWeightFactory();
books.put("java编程思想", factory.new Book("java编程思想","(美)埃克尔著","9782111255837"));
books.put("effective java", factory.new Book("effective java","(美国)Joshua Bloch","9787111255833"));
}
//声明一个私有的构造函数,便自己能调用
private FlyWeightFactory(){
}
public static FlyWeightFactory getInstance(){
return factory;
}
public static baseBook getFlyWeight(String keyname){
return (baseBook) books.get(keyname);
}
/**
相当于“抽象享元角色(接口)”
*/
interface baseBook{
String getName();
String getAutor();
String getISBN();
}
/**
相当于“具体享元角色(实现)”
*/
class Book implements baseBook{
private String name;
private String autor;
private String ISBN;
Book(String name, String autor, String ISBN) {
this.name = name;
this.autor = autor;
this.ISBN = ISBN;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return this.name;
}
@Override
public String getAutor() {
// TODO Auto-generated method stub
return this.autor;
}
@Override
public String getISBN() {
// TODO Auto-generated method stub
return this.ISBN;
}
}
}
package cn.xym.test;
import cn.xym.test.FlyWeightFactory.Book;
import cn.xym.test.FlyWeightFactory.baseBook;
public class Client {
public void buySomeBook(){
baseBook b = FlyWeightFactory.getFlyWeight("java编程思想");
b.getName();
}
}
这样设计后,客户类便不可以自动去new享元对象,这样就可以确保多个客户是共享同一个对象!
图2:
3.在API中找享元设计模式的影子
public class test {
public static void main(String[] args) {
String a = "abc";
String b = "abc";
String c = "ab" + "c";
System.out.println(a == b);
System.out.println(a == c);
}
}
运行结果:
true
true
所以证明存在的字符串“abc”对应的字符串对象只有一个,没有多个!
4.享元模式小结
享元对象的属性必须是不可变的,我们可以将这些不可变的部分提取出来构成一个享元类(interface->concreteclass)
为了能确保享元对象能够被共享,我们还必须提供一个用于创建和查找享元对象的“享元工厂类”,并且保证客户类只能使用该类来创建享元对象
把享元类设置成该类的内部类可以保证享元类只能被享元工厂类访问,这样我们就可以保证客户类只能通过这个享元工厂类对大量使用的对象进行共享访问了.