22.设计模式-享元模式(Flyweight)

享元模式(Flyweight),运用共享技术有效地支持大量细粒度的对象。

内部状态和外部状态:实际场景中实例对象除了几个参数外基本上都是相同的,有时就能够大幅度地减少需要实例化的类的数量。

处理外部状态:如果能把那些参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。

需求

制作多个类似网站,共享相同部分。

代码

业务类

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include "uthash-master-src/src/uthash.h"

typedef struct User {
    char *name;
} User;

User *InitUser(char *name) {
    User *obj = (User *)malloc(sizeof(User));
    obj->name = name;
    return obj;
}

typedef struct Website {
    char *type;
    void (*use)(struct Website *, User *);
} Website;

// Website实例认为是共享的是内部状态,用户数据认为是外部状态
void WebsiteUse(Website *obj, User *user) {
    printf("网站分类:%s 用户:%s\n", obj->type, user->name);
}

Website *InitWebsite(char *type) {
    Website *obj = (Website *)malloc(sizeof(Website));
    obj->type = type;
    obj->use = WebsiteUse;
    return obj;
}

typedef struct Hashtable {
    char *type;
    Website *web;
    UT_hash_handle hh;
} Hashtable;
typedef struct WebsiteFactory {
    Hashtable *hashtable;
    Website *(*GetWebsiteCategory)(struct WebsiteFactory *, char *);
    int (*GetWebsiteCount)(struct WebsiteFactory *);
} WebsiteFactory;

Website *WebsiteFactoryGetWebsiteCategory(WebsiteFactory *obj, char *type) {
    Hashtable *found;
    HASH_FIND_STR(obj->hashtable, type, found);
    // 有相同品类的网站不直接返回,不创建新的实例
    if(found != NULL) {
        return found->web;
    }
    found = (Hashtable *)malloc(sizeof(Hashtable));
    found->type = type;
    found->web = InitWebsite(type);
    HASH_ADD_STR(obj->hashtable, type, found);
    return found->web;
}

int WebsiteFactoryGetWebsiteCount(WebsiteFactory *obj) {
    return HASH_COUNT(obj->hashtable);
}

WebsiteFactory *InitWebsiteFactory() {
    WebsiteFactory *obj = (WebsiteFactory *)malloc(sizeof(WebsiteFactory));
    obj->hashtable = NULL;
    obj->GetWebsiteCategory = WebsiteFactoryGetWebsiteCategory;
    obj->GetWebsiteCount = WebsiteFactoryGetWebsiteCount;
    return obj;
}

客户端

c 复制代码
int main() {
    WebsiteFactory *f = InitWebsiteFactory();
    Website *fx = f->GetWebsiteCategory(f, "产品展示");
    fx->use(fx, InitUser("小菜"));
    Website *fy = f->GetWebsiteCategory(f, "产品展示");
    fy->use(fy, InitUser("骄骄"));
    Website *fl = f->GetWebsiteCategory(f, "博客");
    fl->use(fl, InitUser("老顽童"));
    Website *fm = f->GetWebsiteCategory(f, "博客");
    fm->use(fm, InitUser("桃谷六仙"));
    return 0;
}

尽管给四个不同用户使用网站,但实际上只有两个网站实例。

UML图

总结

  • 享元模式使用场景?
  1. 如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;
  2. 对象的大多数状态是外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享元模式。

实际使用场景,我理解动态库(windows系统的dll库,linux的so库)就是享元模式思想的运用

  • 享元模式让软件设计者在设计类时会思考哪些是外部状态,哪些是内部状态
相关推荐
AI人工智能+电脑小能手17 小时前
大白话说Java设计模式-23-桥接模式(源码剖析篇)
java·设计模式·jdbc·桥接模式·源码分析·awt·java logging
嘟嘟071719 小时前
TypeScript 工具类型通关:Pick、Omit、Partial、Record 区别与 Omit 等价实现一次讲清
设计模式·面试·typescript
SL_staff20 小时前
中小离散制造如何用工艺路线模板解决‘人走流程丢’——JVS-APS 实践解析
java·设计模式·全栈
Asize20 小时前
3 种设计模式 + DI:Nest.js 后端第一课
后端·设计模式·nestjs
Chasing__Dreams21 小时前
Redis--基础知识点--33--String Hash List Set ZSet
redis·list·哈希算法
三8441 天前
webshell缓存绕过/哈希碰撞
算法·哈希算法
St_rive1 天前
Page Object设计模式
java·开发语言·设计模式
星恒随风2 天前
C++ 哈希详解(二):开放定址、哈希桶与 C++ 哈希表底层实现
c++·笔记·学习·哈希算法·散列表
lingran__2 天前
C++ STL unordered系列(哈希) 底层剖析与模拟实现万字详解 | 基于哈希表,复刻 SGI-STL 泛型哈希容器架构
开发语言·c++·后端·哈希算法·哈希表·泛型编程·unordered系列
烬羽2 天前
NestJS 依赖注入:Controller 里那个没有 new 的 service,到底从哪来的?
设计模式·typescript·nestjs