前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >18.设计模式--享元模式(Flyweight模式)

18.设计模式--享元模式(Flyweight模式)

作者头像
大猫的Java笔记
发布2021-11-18 13:21:08
2310
发布2021-11-18 13:21:08
举报
文章被收录于专栏:大猫的Java笔记大猫的Java笔记

1.定义

享元模式是一种结构型模式,如果一个对象实例一经创建就不可变,那么反复创建相同的实例就没有必要,直接向调用方返回一个共享的实例就行,这样即节省内存,又可以减少创建对象的过程,提高运行速度。

在使用Integer的时候当使用的值在-128~127的时候,实际上并不会创建新的Integer,而是使用原来的,为了就是避免重复创建。

在图书中我们有多个书籍,书籍包含了作者以及书名等信息,但是图书馆的书并不是白来的,当然是自己去购买的。如果学生想看的书没有那么就需要去购买,也就是创建Book对象,但是如果存在了那么就不需要去购买,而是直接使用。

2.享元模式结构图

享元模式的结构图非常简单,其中BookFactory相当于工厂,用于书籍的生产,同时通过Map,进行书籍的缓存以及查看是否图书馆存在此书,只有不存在的时候才创建,存在直接使用缓存的书籍,而Book则是书的实体类,其中有书名和作者等基本信息。

3.享元模式实现

Book类实际上只是简单的定义了书名和书的作者,而构造方法使用protected的原因是权限只给同包以及子类的调用,也就是为了只给BookFactory进行生产,而不允许其他的调用者直接使用new Book()的操作。如果一旦使用那么我们的享元模式就没啥用了。

代码语言:javascript
复制
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实例。

代码语言:javascript
复制
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;
    }

}

实际测试如下,当创建的书名字和作者是一样的时候,此时不会新产生实例,而是使用缓存中的实例。

代码语言:javascript
复制
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);
    }
}
代码语言:javascript
复制
Book{name='图解设计模式', author='结城浩'}
Book{name='图解设计模式', author='结城浩'}
true

享元模式中的角色

Flyweight(轻量级),表示需要被共享的实例,可以理解为如果某个对象的创建太大或者说没必要频繁创建的时候,这个对象就是Flyweight角色,在文中由Book类扮演此角色。

FlyweightFactory(轻量级工厂),用于对Flyweight角色的创建,在文中由BookFactory类扮演此角色。

Client(请求者),需要使用轻量级角色的人,即需要使用Book的人,在文中由Test类扮演此角色。

参考文献《图解设计模式》

代码获取地址:https://gitee.com/bughong/design-pattern

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-11-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大猫的Java笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档