加入收藏 | 设为首页 | 会员中心 | 我要投稿 三明站长网 (https://www.0598zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

Java达成享元模式-Flyweight

发布时间:2021-11-12 17:14:57 所属栏目:教程 来源:互联网
导读:享元模式-Flyweight 享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。 本文中的例子如下: 使用享元模式: 小明想看编程技术的书, 就到家里的书架上拿, 如果有就直接看, 没有就去买一本, 回家看

享元模式-Flyweight
享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。
 
本文中的例子如下:
 
使用享元模式: 小明想看编程技术的书, 就到家里的书架上拿, 如果有就直接看, 没有就去买一本, 回家看. 看完了就放到家里的书架上, 以后再想看了直接就在书架上拿, 不需要再去买同样的这本书了.
 
不适用享元模式: 小明想看编程技术的书, 就去书店里买一本回家看, 买完后看完了, 书就不知道丢到了哪里去了. 下次想看的时候就找不到了, 还是得去书店里重新买......又得花钱....然而并不长记性, 这回买完了, 看完了, 又丢到一边...下次还是得再买...
 
Java中实例化一个对象 vs 小明买一本书
 
在Java中的实例化一个对象, 就像是在买一本书, Java中的对象会随着作用域的退出, 对象会失去引用, 过后就会被垃圾收集器标记, 进行回收.
 
就相当于小明买完了一本书, 书就丢到了一边, 妈妈收拾屋子就把这本书识别为了垃圾, 就给扔掉了. (被妈妈收走是被动导致的小明每次都重新买一本书, 也有可能小明主动地每次看书都重新买一本, 有钱任性...这种有钱人性的行为在编程语言里就是每次都new一个对象, 而从来不去考虑复用)
 
Java中把对象放进一个容器里进行维护 vs 小明看完书把书放到书架上 (下面的相同颜色表示相同的行为, 可以互相对照)
 
在Java中:  使用完一个临时实例化的对象后, 如果以后还想复用, 那么就可以放到一个容器里(对象管理器), 或者更直接的说就比如存到一个HashMap里, 需要用的时候以后从里面直接取出来. 这样HashMap对实例化的对象持有引用, 就不会被GC了, 这样该对象就可以常驻内存, 可以复用了, 不用再实例化同样的一个对象了.
 
小明:    看完了一本书, 把书放到了书架上, 这样妈妈就知道这本书是小明需要的东西, 就不会把它当成垃圾来处理. 这样这本书就会一直在家里存在, 小明想看的时候, 就到家里的书架拿就可以看了, 不用再重新买同样的一本书了.
 
BooK接口
书的统一定义.书在本里子中是享元模式里被共享的对象. 应该被放到书架上复用, 而不是买次都重新买.
 
/**
 * 书的统一抽象, 书可以被读
 */
public interface Book {
    void read();
}
 
HeadFirstJavaScript类
 
/**
 * <<HeadFirst JavaScript>>
 */
public class HeadFirstJavaScript implements Book {
 
    @Override
    public void read() {
        System.out.printf("这是一本<<HeadFirst JavaScript>>. (书的编号是:%s)n", System.identityHashCode(this));
    }
}
 
KotlinInAction类
 
/**
 * <<Kotlin实战>>
 */
public class KotlinInAction implements Book {
 
    @Override
    public void read() {
        System.out.printf("这是一本<<Kotlin实战>>. (书的编号是:%s)n", System.identityHashCode(this));
    }
}
 
PythonCookBook类
 
/**
 * <<Python编程手册>>
 */
public class PythonCookBook implements Book {
    @Override
    public void read() {
        System.out.printf("这是一本<<Python编程手册>>. (书的编号是:%s)n", System.identityHashCode(this));
    }
}
 
BookFactory类
 
import java.util.EnumMap;
import java.util.Map;
 
public class BookFactory {
 
    public enum BookType {
        PYTHON, JAVASCRIPT, KOTLIN
    }
 
    private final Map<BookType, Book> shelf;
 
    public BookFactory() {
        shelf = new EnumMap<>(BookType.class);
    }
 
    /**
    * 想读一本书的话就通过这里来get.
    * 如果书架里有, 那么就从书架里拿
    * 如果书架里没有, 那么就从书店买一本看, 然后放到书架上
    */
    public Book getBook(BookType type) {
        Book book = shelf.get(type);
        if (book == null) {
            switch (type) {
                case PYTHON:
                    book = new PythonCookBook();
                    shelf.put(type, book);
                    break;
                case JAVASCRIPT:
                    book = new HeadFirstJavaScript();
                    shelf.put(type, book);
                    break;
                case KOTLIN:
                    book = new KotlinInAction();
                    shelf.put(type, book);
                    break;
                default:
                    break;
            }
        }
        return book;
    }
}
 
 
Main
运行/模拟场景
 
public class Main {
 
    public static void main(String[] args) {
        BookFactory bookFactory = new BookFactory();
 
        bookFactory.getBook(BookFactory.BookType.JAVASCRIPT).read();
        bookFactory.getBook(BookFactory.BookType.JAVASCRIPT).read();
 
        bookFactory.getBook(BookFactory.BookType.PYTHON).read();
        bookFactory.getBook(BookFactory.BookType.PYTHON).read();
 
        bookFactory.getBook(BookFactory.BookType.KOTLIN).read();
        bookFactory.getBook(BookFactory.BookType.KOTLIN).read();
        bookFactory.getBook(BookFactory.BookType.KOTLIN).read();
 
        // 书的编号一样, 说明书复用了, 而不是每次都买一个新的
    }
}
 
结果如下 :
 
 
 
如果对象不是共享的, 也就是非享元模式, 那么<<Kotlin实战>>的三次的书编号都会是不一样的, 因为每次看这本书, 都是新买的, 最终会导致买三次<<Kotlin实战>>这本书, 同样的书买三次多浪费啊.  而本文的例子使用了享元模式, 拿了三次<<Kotlin实战>>这本书, 每次编号都是1360875712, 说明从头到尾都是同一本书, 没有造成浪费.

(编辑:三明站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!