当前位置: 首页 > news >正文

网站向哪里备案深圳龙岗现在算什么风险地区

网站向哪里备案,深圳龙岗现在算什么风险地区,实现网站"今天访问量昨天访问量"统计插件 for dedecms,建设网站可以先买域名吗重修设计模式-结构型-享元模式 复用不可变对象,节省内存 享元模式(Flyweight Pattern)核心思想是通过共享对象方式,达到节省内存和提高性能的目的。享元对象需是不可变对象,因为它会被多处代码共享使用,要避…

重修设计模式-结构型-享元模式

复用不可变对象,节省内存

享元模式(Flyweight Pattern)核心思想是通过共享对象方式,达到节省内存和提高性能的目的。享元对象需是不可变对象,因为它会被多处代码共享使用,要避免一处代码对享元进行了修改,影响到其他使用它的代码。

享元模式的实现非常简单,主要是通过工厂模式,在工厂类中,通过一个 Map 或者 List 来缓存已经创建过的享元对象,来达到复用的目的。

举个例子,在线象棋游戏:

象棋可同时容纳上万个房间同时进行游戏,每个房间最基础的是象棋和棋盘。一副象棋有32个棋子,如果后每个房间都创建相同的棋子对象,就是千万级别的,对任何系统都是个挑战。

分析这个例子,棋子的字和颜色是固定的几个,跟场景无关;场景相关的只有只有棋子的坐标。那其实可以把棋子不变的部分抽取出来,设计为享元对象,让所有棋子共享,从而让每个棋子对象变得更轻量。

未使用享元模式的棋子对象:

//棋子
data class ChessPieceOld(val id: Long,val text: String,val color: ChessPieceUnit.Color,val positionX: Int,val positionY: Int
) {
}

当对象大量创建时,几个固定的属性(id、text、color)会大量重复,冗余占用内存。这时可以将这几个属性抽出,设计为享元类,并使用带缓存的工厂来生成享元对象:

//棋子固定信息-享元类
data class ChessPieceUnit(val id: Long, val text: String, val color: Color) {enum class Color {RED, BLACK}
}//生成棋子-带缓存的创建工厂
class ChessPieceFactory {companion object {//享元对象池private val chessPiece = hashMapOf(1 to ChessPieceUnit(1, "車", ChessPieceUnit.Color.RED),2 to ChessPieceUnit(2, "馬", ChessPieceUnit.Color.BLACK),//...)fun getChessPiece(id: Int): ChessPieceUnit {return chessPiece[id]!!}}
}//棋子
data class ChessPiece(val piece: ChessPieceUnit, val positionX: Int, val positionY: Int) {
}//棋盘
class ChessBoard() {private val chessPieces: HashMap<Int, ChessPiece> = hashMapOf()fun init() {chessPieces.put(1, ChessPiece(ChessPieceFactory.getChessPiece(1), 0, 1))chessPieces.put(2, ChessPiece(ChessPieceFactory.getChessPiece(1), 0, 1))//...}fun move(chessPieceId: Int, positionX: Int, positionY: Int) {//...}
}

使用享元后,所有棋子的固定部分共同引用数量有限的享元对象,每个棋子对象变得更为轻量,内存中存储的冗余信息大大减少,避免了大量相似对象的开销,提高了系统资源的利用率。

注意上面的例子,使用享元模式后,棋子对象的数量并没有变化,只是对象比之前小了很多。消耗内存最多的成员变量已经被移动到很少的几个享元对象中了,这几个享元对象会被上千个情境小对象复用,无需再重复存储相同数据。

享元模式在 Java 语言中的应用

1.Java 中的字符串常量池

String 类会利用享元模式来复用相同的字符串常量,当某个字符串常量第一次被用到的时候,存储到常量池中,之后再用到的时候,直接引用常量池中已经存在的即可,不需要重复创建对象,通过下面代码可以验证。

//字符串常量池
String s1 = "秋意浓";
String s2 = "秋意浓";
String s3 = new String("秋意浓");//直接new出对象,绕过了Java的常量池优化
System.out.println(s1 == s2);   //输出:true
System.out.println(s1 == s3);   //输出:false

2.基本类型包装类

基本类型的包装类(如Integer 、Long、Short、Byte 等),也都利用了享元模式来缓存 -128 到 127 之间的数据。因为对于大部分应用来说这个区间是最常用的数值,如果预先创建所有值的享元对象不仅会占用大量内存,也会让类加载时间过长。

以 Integer 类型为例:

//包装类型的享元
Integer n1 = 1;
Integer n2 = 1;
Integer n3 = 129;
Integer n4 = 129;
System.out.println(n1 == n2);   //输出:true
System.out.println(n3 == n4);   //输出:false

因为 129 超出了享元对象池区间,所以每次会返回新的对象,两个对象地址不同,输出 false。Integer 享元部分源码如下:

public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);
}
private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {}
}

可以通过 JDK 参数修改缓存池上限(下限不支持修改):

//方法一:
-Djava.lang.Integer.IntegerCache.high=255
//方法二:
-XX:AutoBoxCacheMax=255

在使用 Java 进行编码时,要尽量避免直接 new 出包装类型或者字符类型对象,如 String s = new String("aaa")Integer n = new Integer(1),这样会绕过系统的享元模式,创建重复对象。推荐直接使用自动装箱语法,如:Integer n = 1,或通过类型工厂的方式:Integer n = Integer.valueof(1)

上面两个场景都是享元模式在 Java 中的应用,只是实现略有不同:Integer 类中要共享的对象,是在类加载的时候就一次性创建好的;String 类的享元,是在某个字符串第一次被用到的时候,才创建并存储到常量池中的,相当于懒加载方式。

享元模式的类似设计

1.享元模式 vs 单例

虽然享元模式的实现和单例的变体多例非常相似,但它们的设计意图不同:享元模式是为了对象复用,节省内存。而多例是为了限制对象的个数。

2.享元模式 vs 对象池

虽然享元模式和对象池都是为了复用,但他们的“复用”也是不同的概念:

  • 对象池中的“复用”可以理解为“重复使用”,使用时被使用者独占,使用完成后放回池中,主要目的是节省时间。
  • 享元模式中的“复用”可以理解为“共享使用”,在整个生命周期中,都是被所有使用者共享的,主要目的是节省空间。

总结

当一个系统中存在大量重复对象的时候,我们就可以利用享元模式,将对象设计成享元,在内存中只保留一份实例,供多处代码引用,这样可以减少内存中对象的数量,以起到节省内存的目的。

http://www.yayakq.cn/news/543239/

相关文章:

  • 营销型网站策划公司广州市公司网站建设报价
  • 贺州网络推广网站优化的常见问题
  • 自己的网站可以做淘客吗备案ip 查询网站查询网站
  • 网站支付怎么做虚拟币支付淘宝客 网站建设
  • 郑州网站制作公司名单哪个网站可以学做咸菜
  • 个人网站 备案 类型淮安市建设局网站首页
  • 营销网站制作方案天辰建设网站公司
  • win7 iis配置网站 视频教程wordpress菜单锚点定位
  • 做seo网站诊断书怎么做广州 骏域网站建设 陶瓷
  • 小组用jsp做的网站论文网站建设制作设计公司
  • wordpress免费网页建站移动端网站怎么做外链
  • 网站监控怎么做地方房地产网站seo实战案例分享
  • 微信网站怎么收款产品设计ppt案例
  • 钓鱼网站怎么制作html北京高端网站设计外包公司
  • 百度云 免费 网站主机网站建站公司模板
  • 出口手工艺品网站建设方案台州wordpress
  • 网站建设好公司哪家好网站后台域名登陆软件
  • 一般网站使用什么做的网站开发vs2015是什么
  • 重庆网站建设 狐灵分类用wordpress
  • 建设网站怎么学兖矿东华建设有限公司网站
  • 建晨网站建设有限公司优秀网站配色
  • 建设一个网站需要考虑什么怎么开小程序店铺
  • 中投建设官方网站查企业营业执照的网站
  • 天津网站建设费用免费商标设计网站
  • 做效果图常用的网站三大主流app开发平台
  • 北京网站开发服务seo软件推广哪个好
  • 软装潢.企业网站建设百度网页版入口官网
  • 辽宁省建设部网站wordpress商店网页
  • 微信公众号注册流程seo应用领域有哪些
  • 网站建设音乐代码photoshop下载安装