设计模式---享元(FlyWeight)模式

1 引言

在程序设计中,有时会面临创建大量相同或者相似对象实例的场景,比如围棋的黑白子,教室里的桌椅。如果把相似的地方抽象出来共享,则可以大量的节省系统资源,提升系统性能,所对应的就是享元模式。

2 定义

享元模式:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。

3 内部状态与外部状态

内部状态是指在享元内部共享的信息,比如教室的椅子其组成材质,形状规格,结构都是相同的,完全可以共享。

外部状态是指享元不能共享的信息,此信息会随着环境的改变而改变,比如教室桌椅的当前使用者的信息。

4 结构与实现

享元模式包含4个重要的角色,分别是:

1.抽象的享元(FlyWeight)角色,是所有的具体享元类的基类,是具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。

2.具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。

3.非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。

4.享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。

结构如下图所示(图来自引用2):

5 优缺点

享元模式的主要优点是:相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。

其主要缺点是:

1.为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。

2.读取享元模式的外部状态会使得运行时间稍微变长。

6 代码示例

对于同一个网站,我们不需要创建不同的实例对象,只是使用的用户不同,同一实例不同用户。

6.1 定义用户 User

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-10-22 15:23
 **/
@Data
@AllArgsConstructor
public class User {
    /**
     * 用户名
     */
    private String name;

    /**
     * 简介
     */
    private String desc;

}

6.2 抽象的享元 Website

**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-10-22 11:28
 * @desc: 抽象享元接口
 **/
public interface Website {

    /**
     * 发布博客
     * @param user 用户
     */
    void postBlog(User user);


    /**
     * 上传图片
     * @param user 用户
     */
    void uploadPicture(User user);
}

6.3 具体的享元 ConcreteWebsite

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-10-22 15:22
 **/
public class ConcreteWebsite implements Website{

    @Override
    public void postBlog(User user) {
        System.out.println(MessageFormat.format("{0}用户,简介是{1},上传博客", user.getName(), user.getDesc()));
    }

    @Override
    public void uploadPicture(User user) {
        System.out.println(MessageFormat.format("{0}用户,简介是{1},上传图片", user.getName(), user.getDesc()));
    }
}

6.4 工厂 Factory

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-10-22 15:28
 **/
public class Factory {
    private Map<String, Website> websites = new HashMap<>();


    public  Website getWebsite(String key){
        if (websites.containsKey(key)){
            return websites.get(key);
        }
        Website website = new ConcreteWebsite();
        websites.put(key, website);
        return website;
    }
}

6.5 主程序

/**
 * @program: design-pattern-learning
 * @author: zgr
 * @create: 2021-10-22 11:27
 **/
public class MainClass {
    public static void main(String[] args) {
        Factory factory = new Factory();
        Website website11 = factory.getWebsite("csdn");
        Website website12 = factory.getWebsite("csdn");
        Website website21 = factory.getWebsite("zhihu");
        Website website22 = factory.getWebsite("zhihu");

        website11.postBlog(new User("张三", "助理工程师"));
        website11.uploadPicture(new User("张三", "助理工程师"));
        website12.postBlog(new User("李四", "中级工程师"));
        website12.uploadPicture(new User("李四", "中级工程师"));

        website21.postBlog(new User("王五", "副高级工程师"));
        website21.uploadPicture(new User("王五", "副高级工程师"));
        website22.postBlog(new User("赵六", "高级工程师"));
        website22.uploadPicture(new User("赵六", "高级工程师"));
    }
}

6.6 运行结果

7 引用 

1 《大话设计模式》

享元模式(详解版)

8 源代码

https://github.com/airhonor/design-pattern-learning/tree/main/src/com/hz/design/pattern/flyweight

猜你喜欢

转载自blog.csdn.net/honor_zhang/article/details/120901850