享元模式

享元模式,英文为Flyweight Pattern,fly weight翻译过来即轻量级(可以飞起来的重量,就是轻量级啊)

享元模式的本质:对象复用(节省内存空间,提升系统性能)

解释:假如你需要1000个对象A,而这1000个对象有非常多的属性或状态都是一样的(不会改变),只有一部分属性或状态不一样(随外界需求而变)。我们将这些一致的不变的属性称之为内部状态,将随外界环境(其实就是客户需求)的改变而改变的属性称之为外部状态。

举个例子,假如在设计游戏的时候,在一些场景下,需要1000个小兵,这1000个小兵只是在地图上的位置不同,但战斗力都相同。这里小兵的战斗力就是小兵的内部状态,而小兵的位置就是小兵的外部状态。

再举个例子,还有五子棋、围棋等游戏,假如需要100个棋子,这些棋子的位置是随时改变的,而棋子的归属(哪个玩家的)、棋子的颜色(一般同一玩家的棋子颜色一致)都是不会变化的,这里位置就是棋子的外部状态,而棋子的归属、颜色就是棋子内部状态。

再再举一个例子,假如系统中有10本书,然后每本书有1000个订单,现在这10*1000个订单的信息(每个订单中要包含对应书的信息)。对这10*1000个订单而言,订单自身信息(如下单人、下单时间、金额等)是不一样的,就是外部信息,而对于订单中包含的书的信息则属于内部状态,只有10种,系统中,只要有10个书的实例即可。享元,共享的是这10个书的实例。

示例:上面书与订单的例子

public class Book {

    private String bookName;
    private String author;
    private int price;

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }
}

订单

public class Order {

    private String username;
    private Book book;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }
}

生成订单

public class OrderFactory {

    private static final Map<String, Book> books = new HashMap<>();

    public static Order generateOrder(String username, String bookName){
        Order order = new Order();
        order.setUsername(username);
        if(books.containsKey(bookName)){
            order.setBook(books.get(bookName));
        }else {
            Book book = createNewBookInstance(bookName);
            order.setBook(book);
            books.put(bookName,book );
        }
        return order;
    }

    private static Book createNewBookInstance(String bookName){
        //演示,实际可能是去数据库等获取具体信息
        Book book = new Book();
        book.setBookName(bookName);
        book.setAuthor("maxwell");
        book.setPrice(new Random().nextInt(100));
        return book;
    }
}

客户端

public class Client {

    public static void main(String[] args) {

        //假如只有10种书,每本书有1000个订单,而在某处我们需要将这些订单信息都加载到内存中,
        // 这10*1000个订单实例则会共享这10个书的实例
        // 这样就可以节省[(10*1000 - 10 )* 每个书的实例的大小]的内存空间
        List<Order> orders = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            String bookName = "book" + i;
            for (int j = 0; j < 1000; j++) {
                Order order = OrderFactory.generateOrder("xiaoming" + j, bookName);
                orders.add(order);
            }
        }
    }
}

参考

JAVA设计模式-享元模式(Flyweight)

一起学设计模式 - 享元模式

Last updated