1.定义
享元模式是一种结构型模式,如果一个对象实例一经创建就不可变,那么反复创建相同的实例就没有必要,直接向调用方返回一个共享的实例就行,这样即节省内存,又可以减少创建对象的过程,提高运行速度。
在使用Integer的时候当使用的值在-128~127的时候,实际上并不会创建新的Integer,而是使用原来的,为了就是避免重复创建。
在图书中我们有多个书籍,书籍包含了作者以及书名等信息,但是图书馆的书并不是白来的,当然是自己去购买的。如果学生想看的书没有那么就需要去购买,也就是创建Book对象,但是如果存在了那么就不需要去购买,而是直接使用。
2.享元模式结构图
享元模式的结构图非常简单,其中BookFactory相当于工厂,用于书籍的生产,同时通过Map,进行书籍的缓存以及查看是否图书馆存在此书,只有不存在的时候才创建,存在直接使用缓存的书籍,而Book则是书的实体类,其中有书名和作者等基本信息。
3.享元模式实现
Book类实际上只是简单的定义了书名和书的作者,而构造方法使用protected的原因是权限只给同包以及子类的调用,也就是为了只给BookFactory进行生产,而不允许其他的调用者直接使用new Book()的操作。如果一旦使用那么我们的享元模式就没啥用了。
public class Book {
/**
* 书名
*/
private String name;
/**
* 作者
*/
private String author;
protected Book(String name, String author) {
this.name = name;
this.author = author;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
'}';
}
}
BookFactory中的Map用于缓存实例,实际上应该限制大小,否则如果存放的实例过多会产生OOM,同时BookFactory我们定义为单例模式,因为工厂并不需要多实例,如果多实例后会导致缓存的Book对象到不同的BookFactory中。
而确定书是否存在是通过书名+作者名,毕竟书名相同的太多了。createBook使用synchronized的原因是因为,在并发情况下会导致创建重复的Book实例。
public class BookFactory {
private static final BookFactory bookFactory = new BookFactory();
private Map<String,Book> cache = new HashMap();
private BookFactory() {
}
public static BookFactory getInstance(){
return bookFactory;
}
/**
* 创建书,指定书名和作者
* @param bookName
* @param author
* @return
*/
public synchronized Book createBook(String bookName,String author){
String bookInfo = bookName + ":" + author;
Book oldBook = cache.get(bookInfo);
if(oldBook == null){
Book newBook = new Book(bookName, author);
cache.put(bookInfo,newBook);
return newBook;
}
return oldBook;
}
}
实际测试如下,当创建的书名字和作者是一样的时候,此时不会新产生实例,而是使用缓存中的实例。
public class Test {
public static void main(String[] args) {
Book book = BookFactory.getInstance().createBook("图解设计模式", "结城浩");
System.out.println(book);
Book book2 = BookFactory.getInstance().createBook("图解设计模式", "结城浩");
System.out.println(book2);
System.out.println(book == book2);
}
}
Book{name='图解设计模式', author='结城浩'}
Book{name='图解设计模式', author='结城浩'}
true
享元模式中的角色
Flyweight(轻量级),表示需要被共享的实例,可以理解为如果某个对象的创建太大或者说没必要频繁创建的时候,这个对象就是Flyweight角色,在文中由Book类扮演此角色。
FlyweightFactory(轻量级工厂),用于对Flyweight角色的创建,在文中由BookFactory类扮演此角色。
Client(请求者),需要使用轻量级角色的人,即需要使用Book的人,在文中由Test类扮演此角色。
参考文献《图解设计模式》
代码获取地址:https://gitee.com/bughong/design-pattern