享元模式分析与实践

享元模式分析与实践

  • 一、享元模式与单例模式区别
    • 1、优点
    • 2、缺点
    • 3、享元模式在jdk中的体现
      • 1.1String中的intern()方法
      • 1.2Integer中的vauleOf()方法
  • 二、享元模式与单例模式代码举例
    • 1.1单例模式代码
    • 1.2享元模式代码
  • 三、项目结构及测试结果

享元就是共享单元(元素)的意思。单元代表了整体的部分,如果一个对象其中的部分是稳定的不会改变的,那么这个部分即可以共享。享元模式的用途就是复用对象的单元,让对象的节省内存。

一、享元模式与单例模式区别

单例模式是类级别的,一个类只能有一个对象实例;
享元模式是对象级别的,可以有多个对象实例,多个变量引用同一个对象实例;
享元模式主要是为了节约内存空间,提高系统性能,而单例模式主要为了可以共享数据;

1、优点

(1)节省内存空间,对于可重复的对象只会被创建一次,对象比较多时,就会极大的节省空间。

(2)提高效率,由于创建对象的数量减少,所以对系统内存的需求也减小,使得速度更快,效率更高。

2、缺点

提高了系统复杂性,需要分离出外部状态(k)和内部状态(v),而且外部状态具有固化特性,不应该随内部状态改变而改变,否则导致系统的逻辑混乱,为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。

● 内部状态

内部状态是对象可共享出来的信息,存储在享元对象内部并且不会随环境改变而改变,它们可以作为一个对象的动态附加信息,不必直接储存在具体某个对象中,属于可以共享的部分。

● 外部状态

外部状态是对象得以依赖的一个标记,是随环境改变而改变的、不可以共享的状态,它是一批对象的统一标识,是唯一的一个索引值。

3、享元模式在jdk中的体现

1.1String中的intern()方法

public static void main(String[] args) {String str1 = "法外狂徒";String str2 = "张三";String str3 = "法外狂徒张三";String str4;str4 = str1 + str2;System.out.println(str3 == str4);//如果是String的对象池中有该类型的值,则直接返回对象池中的对象str4 = (str1 + str2).intern();System.out.println(str3 == str4);
}

输出结果:false true

1.2Integer中的vauleOf()方法

在范围[-128, 127]内在Integer缓存中直接取,范围外通过new Integer(i) 生成

        //Integer中的缓存数组 cacheInteger[] cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}Integer i1 = Integer.valueOf(99);Integer i2 = Integer.valueOf(99);System.out.println(i1==i2);Integer i3 = Integer.valueOf(128);Integer i4 = Integer.valueOf(128);System.out.println(i3==i4);

输出结果:true false

二、享元模式与单例模式代码举例

1.1单例模式代码

public class Singleton {// 我来写一个单例模式  懒汉式private static Singleton singleton;private Singleton(){}public static synchronized Singleton getSingleton(){if(singleton==null){singleton=new Singleton();}return singleton;}public static void main(String[] args) {Singleton instance1 = Singleton.getSingleton();Singleton instance2 = Singleton.getSingleton();System.out.println(instance1==instance2);}
}

1.2享元模式代码

定义抽象享元类

/*** 定义抽象享元类*/
public abstract class Book {/*** 外部状态 书名*/public String name;public Book(String name) {this.name = name;}/*** 借书动作*/public abstract void borrow();
}

定义具体享元类

/*** 定义具体享元类*/
public class ConcreteBook extends Book {/*** 被借出的书名*/public ConcreteBook(String name){super(name);}@Overridepublic void borrow() {System.out.println("借了一本书名为:"+this.name);}
}

享元工厂

/*** 享元工厂*/
public class LibraryFactory {/*** 图书馆维护一个图书列表*/private Map<String, Book> bookPools = new HashMap<>();private static LibraryFactory factory = new LibraryFactory();/*** 图书馆只有一个*/public static LibraryFactory getInstance() {return factory;}/*** 图书馆外借图书*/public Book libToBorrow(String bookName) {Book order;//如果书架有书,直接借出if (bookPools.containsKey(bookName)) {order = bookPools.get(bookName);} else {//如果没有,那就拿本新书//根据外部状态创建享元对象order = new ConcreteBook(bookName);//放到池中bookPools.put(bookName, order);}return order;}//书架上书的数量public int getAllBookSize() {return bookPools.size();}
}

控制层

@RestController
@RequestMapping("/studentController")
public class StudentController {/*** 图书馆书架上的书*/private static List<Book> books = new ArrayList<>();private static LibraryFactory libraryFactory;/*** 查询*/@PostMapping("/borrow")@ResponseBodypublic void borrow() {libraryFactory = LibraryFactory.getInstance();studentBorrow("葵花宝典");studentBorrow("僻邪剑谱");studentBorrow("java从入门到放弃");//把每一本书借出去for (Book book : books) {book.borrow();}System.out.println("===========================后两本秘籍没学会,又借了一次 ");studentBorrow("僻邪剑谱");studentBorrow("java从入门到放弃");Book piXieJianPu = libraryFactory.libToBorrow("僻邪剑谱");piXieJianPu.borrow();Book ruMenFangQi = libraryFactory.libToBorrow("java从入门到放弃");ruMenFangQi.borrow();//输出一些学生一共借多少本书System.out.println("学生一共借了 " + books.size() + " 本书! ");//输出一下图书馆一共借出多少本书System.out.println("图书馆实际借出" + libraryFactory.getAllBookSize() + " 本书");}/*** 学生借书,将借的书,记录到图书馆书架列表*/private static void studentBorrow(String bookName) {books.add(libraryFactory.libToBorrow(bookName));}
}

三、项目结构及测试结果

在这里插入图片描述

源码地址SpringBoot2.XLearn 欢迎star
测试结果
在这里插入图片描述
在结果中可以看出:其实学生一共借了5次书,但是有两本是重复的,所以对于图书馆来说,其实是借出去了三本书。
在这里插入图片描述
参考资料
设计模式—享元模式
设计模式之享元模式
享元模式与单例模式区别


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部