本文介绍: 使用共享对象可有效地支持大量的细粒度的对象享元模式对象池的一种实现用来尽可能减少内存使用量,它适合用于可能存在大量重复对象场景,来缓存共享对象,达到对象共享,避免创建过多对象的效果,这样一来就可以提升性能,避免内存溢出等。在享元模式中会建立一个对象容器,在经典的享元模式中该容器为一个Map,它的键是享元对象的内部状态,它的值就是享元对象本身。客户端程序通过这个内部状态享元工厂获取享元对象,如果有缓存,则使用缓存对象,否则创建一个享元对象并且存入容器中,这样一来就避免了创建过多对象的问题

水不激不跃,人不激不奋

一,定义

使用共享对象可有效地支持大量的细粒度的对象

享元模式是对象池的一种实现用来尽可能减少内存使用量,它适合用于可能存在大量重复对象的场景,来缓存可共享的对象,达到对象共享,避免创建过多对象的效果,这样一来就可以提升性能,避免内存溢出等。

享元模式中会建立一个对象容器,在经典的享元模式中该容器为一个Map,它的键是享元对象的内部状态,它的值就是享元对象本身。客户端程序通过这个内部状态从享元工厂获取享元对象,如果有缓存,则使用缓存对象,否则创建一个享元对象并且存入容器中,这样一来就避免了创建过多对象的问题。

二,使用场景

1,系统中存在大量的相似对象

2,细粒度的对象都具备较接近的外部状态,而且内部状态环境无关,就是说对象没有特定身份

3,需要缓冲池的场景

三,角色介绍

Flyweight:享元对象抽象基类或接口

ConcreteFlyweight:具体的享元对象

FlyweightFactory:享元工厂,负责管理享元对象池和创建享元对象

四,使用案例

假设在吃鸡游戏中,每局游戏都会有100个玩家参与游戏,所以每局游戏都会创建100个玩家角色,如果一个玩家进行了10局游戏,他的角色就会被创建10次。这样就会造成频繁的GC,从而影响性能。如果我们使用享元模式,将玩家的姓名作为key,玩家角色作为value存放在内存中,这样就不会频繁的去创建玩家角色,避免造成不必要的资源浪费。

首先,创建一个玩家角色接口作为享元对象抽象接口,该接口定义玩家自己选择皮肤玩游戏

public interface Player {
    
    /**
     * 玩游戏
     * @param skin 自己选择的皮肤
     * */
    void playGame(String skin);
}

然后创建具体的享元对象 :

public class ConcretePlayer implements Player{

    private String name;

    public ConcretePlayer(String name) {
        this.name = name;
    }

    @Override
    public void playGame(String skin) {
        System.out.println("玩家"+name+"使用"+skin+"角色玩游戏");
    }
}

最后创建享元工厂

public class PlayerFactory {

    private static HashMap<String,Player> map =new HashMap<>();

    public static Player createPlayer(String name){
        if(map.get(name)==null){
            System.out.println("创建新的角色");
            ConcretePlayer concretePlayer =new ConcretePlayer(name);
            map.put(name,concretePlayer);
            return concretePlayer;
        }else {
            System.out.println("从缓存中拿取角色");
            ConcretePlayer player = (ConcretePlayer) map.get(name);
            return player;
        }
    }
}

使用:

Player player = PlayerFactory.createPlayer("N港之王");
player.playGame("红螳螂");
Player player1 = PlayerFactory.createPlayer("N港之王");
player1.playGame("黄螳螂");
Player player2 = PlayerFactory.createPlayer("N港之王");
player2.playGame("紫螳螂");

输出

这样,即使玩家使用同一角色玩了好多把游戏,都只创建了一次角色,其余的都是从缓存获取

五,总结

享元模式实现比较简单,但是它的作用在某些场景确实及其重要。它可以大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能,但它同时也提高系统的复杂性,需要分离出外部状态和内部状态,而且外部状态具有固化特性,不应该随内部状态改变而改变,否则导致系统逻辑混乱。

享元模式的优点在于它大幅度地降低内存中对象的数量,但是,它做到这一点所付出的代价也是很高的。

享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。

享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。

参考文献:Android源码设计模式解析实战

原文地址:https://blog.csdn.net/y2653904/article/details/134608278

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_4775.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注