享元模式-Flyweight(Java實現)

享元模式-Flyweight

享元模式的主要目的是實現對象的共享,即共享池,當系統中對象多的時候能夠減小內存的開銷,一般與工廠模式一塊兒使用。java

本文中的例子以下:編程

使用享元模式: 小明想看編程技術的書, 就到家裏的書架上拿, 若是有就直接看, 沒有就去買一本, 回家看. 看完了就放到家裏的書架上, 之後再想看了直接就在書架上拿, 不須要再去買一樣的這本書了.編程語言

不適用享元模式: 小明想看編程技術的書, 就去書店裏買一本回家看, 買完後看完了, 書就不知道丟到了哪裏去了. 下次想看的時候就找不到了, 仍是得去書店裏從新買......又得花錢....然而並不長記性, 這回買完了, 看完了, 又丟到一邊...下次仍是得再買...ide

 

Java中實例化一個對象 vs 小明買一本書this

在Java中的實例化一個對象, 就像是在買一本書, Java中的對象會隨着做用域的退出, 對象會失去引用, 事後就會被垃圾收集器標記, 進行回收.spa

就至關於小明買完了一本書, 書就丟到了一邊, 媽媽收拾屋子就把這本書識別爲了垃圾, 就給扔掉了. (被媽媽收走是被動致使的小明每次都從新買一本書, 也有可能小明主動地每次看書都從新買一本, 有錢任性...這種有錢人性的行爲在編程語言裏就是每次都new一個對象, 而歷來不去考慮複用)對象

 

Java中把對象放進一個容器裏進行維護 vs 小明看完書把書放到書架上 (下面的相同顏色表示相同的行爲, 能夠互相對照)blog

在Java中:   使用完一個臨時實例化的對象後, 若是之後還想複用, 那麼就能夠放到一個容器裏(對象管理器), 或者更直接的說就好比存到一個HashMap裏, 須要用的時候之後從裏面直接出來. 這樣HashMap對實例化的對象持有引用, 就不會被GC了, 這樣該對象就能夠常駐內存, 能夠複用了, 不用再實例化一樣的一個對象了.接口

小明:    看完了一本書, 把書放到了書架上, 這樣媽媽就知道這本書是小明須要的東西, 就不會把它當成垃圾來處理. 這樣這本書就會一直在家裏存在, 小明想看的時候, 就到家裏的書架就能夠看了, 不用再從新買一樣的一本書了.ip

 

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, 說明從頭至尾都是同一本書, 沒有形成浪費.

相關文章
相關標籤/搜索