在程序设计中,有时会面临创建大量相同或者相似对象实例的场景,比如围棋的黑白子,教室里的桌椅。如果把相似的地方抽象出来共享,则可以大量的节省系统资源,提升系统性能,所对应的就是享元模式。
享元模式:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。
内部状态是指在享元内部共享的信息,比如教室的椅子其组成材质,形状规格,结构都是相同的,完全可以共享。
外部状态是指享元不能共享的信息,此信息会随着环境的改变而改变,比如教室桌椅的当前使用者的信息。
享元模式包含4个重要的角色,分别是:
1.抽象的享元(FlyWeight)角色,是所有的具体享元类的基类,是具体享元规范需要实现的公共接口,非享元的外部状态以参数的形式通过方法传入。
2.具体享元(Concrete Flyweight)角色:实现抽象享元角色中所规定的接口。
3.非享元(Unsharable Flyweight)角色:是不可以共享的外部状态,它以参数的形式注入具体享元的相关方法中。
4.享元工厂(Flyweight Factory)角色:负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
结构如下图所示(图来自引用2):
享元模式的主要优点是:相同对象只要保存一份,这降低了系统中对象的数量,从而降低了系统中细粒度对象给内存带来的压力。
其主要缺点是:
1.为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。
2.读取享元模式的外部状态会使得运行时间稍微变长。
对于同一个网站,我们不需要创建不同的实例对象,只是使用的用户不同,同一实例不同用户。
/**
* @program: design-pattern-learning
* @author: zgr
* @create: 2021-10-22 15:23
**/
@Data
@AllArgsConstructor
public class User {
/**
* 用户名
*/
private String name;
/**
* 简介
*/
private String desc;
}
**
* @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);
}
/**
* @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()));
}
}
/**
* @program: design-pattern-learning
* @author: zgr
* @create: 2021-10-22 15:28
**/
public class Factory {
private Map 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;
}
}
/**
* @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("赵六", "高级工程师"));
}
}
1 《大话设计模式》
2 享元模式(详解版)
https://github.com/airhonor/design-pattern-learning/tree/main/src/com/hz/design/pattern/flyweight