定义:
在一个系统中存在多个相同的对象,则只需要共享一份对象的拷贝,而不必为每一次使用创建新对象,为提升系统性能而生的设计模式,它的主要作用是复用大对象(重量级对象),节省内存空间和对象创建时间
组成:
角色 | 作用 |
---|---|
享元工厂 | 具体享元类,用来维护相同的享元对象,判断某个对象是否已经存在,存在则直接返回该对象,不存在的话则创建该对象 |
抽象享元 | 定义需共享对象的业务接口,并定义需要始终实现的某些特定业务逻辑 |
具体享元类 | 实现抽象享元类接口的类,完成各自具体的业务逻辑 |
主函数 | 调用享元模式组件,通过享元工厂获取享元对象 |
实现:
抽象享元
public interface IEnjoyInterface {
void outStr();
void setTranceName(String tranceName);
}
具体享元类:
public class EnjoyTeacherImp implements IEnjoyInterface{
//享元类1
protected String tranceId;
protected String tranceName;
public EnjoyTeacherImp(String truncId){
this.tranceId=truncId;
System.out.println("老师对象建立");
}
@Override
public void outStr() {
System.out.println("老师:"+tranceName);
}
@Override
public void setTranceName(String tranceName) {
this.tranceName=tranceName;
}
}
public class EnjoyStudentImp implements IEnjoyInterface {
protected String tranceId;
protected String tranceName;
public EnjoyStudentImp(String truncId){
this.tranceId=truncId;
System.out.println("学生对象建立");
}
@Override
public void outStr() {
System.out.println("学生:"+tranceName);
}
@Override
public void setTranceName(String tranceName) {
this.tranceName=tranceName;
}
}
享元工厂:
public class EnjoyFactory {
static Map<String,IEnjoyInterface> teacherManger=new ConcurrentHashMap<>();
static Map<String,IEnjoyInterface> studentManger=new ConcurrentHashMap<>();
public static IEnjoyInterface getManager(String type,String tranceId){
IEnjoyInterface ret;
switch (type){
case "TEACHER":
ret=teacherManger.get(tranceId);
break;
case "STUDENT":
ret=studentManger.get(tranceId);
break;
default:
ret=null;
}
if(ret==null){
//判断对象是否已经存在
ret=setManager(type,tranceId);
}
return ret;
}
private static IEnjoyInterface setManager(String type, String tranceId){
IEnjoyInterface ret;
switch (type){
case "TEACHER":
ret=new EnjoyTeacherImp(tranceId);
teacherManger.put(tranceId,ret);
break;
case "STUDENT":
ret=new EnjoyStudentImp(tranceId);
studentManger.put(tranceId,ret);
break;
default:
ret=null;
}
return ret;
}
}
主函数:
public class TestApp {
public static void main(String[] args){
outStr("TEACHER","A","A1",true);
outStr("STUDENT","B","B1",true);
outStr("TEACHER","A","A2",false);
outStr("STUDENT","B","B2",false);
}
private static void outStr(String type, String tranceId, String tranceName, boolean syn){
new Thread(){
@Override
public void run() {
IEnjoyInterface rf=EnjoyFactory.getManager(type,tranceId);
rf.setTranceName(tranceName);
if(syn){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
rf.outStr();
}
}.start();
}
}
输出结果:
优点:
- 节省重复创建对象的开销,相同对象只会创建一次,如果创建对象比较耗时,会节省大量时间
- 创建对象数量的减少,也会对系统内存需求较少,减低GC压力
缺点:
由案例执行结果可见第一个和第二个线程,分别被第三和第四个线程修改了输出值【tranceName】,可见在多线程并发情况下,是线程不安全的,所以我们在使用时应该避免[set]操作,只提供[get]的对外接口,避免数据修改
应用场景:
缓存:联想至缓存机制 caffeine