首页 > 编程知识 正文

原型模式和享元模式区别,对象池和享元模式的根本不同

时间:2023-05-04 10:49:00 阅读:167760 作者:4246

一.什么是享元模式? 享元模式(Flyweight pattern )也称为轻量模式,是象池的一种标签。 与线程池一样,线程池可以不断地避免创建和销毁对象,从而消耗性能。 享受元模型可以减少对象数量,其宗旨是共享细粒度的对象,汇总对同一对象的多个访问,是一种结构型设计模型

二.享元模式写法极高uml图1 .享元模式uml图:

主要的三个作用

1. 抽象享元角色(IFlyweight):元对象抽象基类或接口,同时定义对象外部和内部状态的接口或实现。

2. 具体享元角色(ConcreteFlyweight):实现抽象角色定义的业务。 这个作用的内部状态处理应该与环境无关地进行,根据操作内部状态会发生变化,同时外部状态不会发生变更

3. 享元工厂(FlyweightFactory):负责管理共享源连接池和创建共享源对象

tip:通过例子详细地知道外部状态和内部状态是什么

2 .一般写法IFlyweight :

/** *抽象元角色*/publicinterfaceiflyweight { void operation (stringextrinsicstate ); } ConcreteFlyweight:

/** *具体元作用*/publicclassconcreteflyweightimplementsiflyweight { privatestringintrinsicstate; publicconcreteflyweight (stringintrinsicstate (this.intrinsic state=intrinsic state ); } @ overridepublicvoidoperation (stringextrinsicstate ) system.out.println ' object address 3360 ' system.identityhatatatation system.out.println (intrinsicstate : ) intrinsic state ); }} FlyweightFactory :

/**享元工厂*/publicclassflyweightfactory { publicstaticmapstring,iflyweightpool=newconcurrenthashmap (; publicstaticiflyweightgetflyweight (stringintrinsicstate ) if (! pool.contains key (intrinsic state ) iflyweightflyweight=newconcreteflyweight (intrinsic state ); pool.put(intrinsicstate,flyweight ); }returnpool.get(intrinsicstate; }结果:

public class client { publicstaticvoidmain (string [ ] args ) iflyweightflyweight flyweight factory.get flyweight (' aa ' id ) iflyweightflyweight3=flyweight factory.get flyweight (' cc ' ); lyweight1.operation('wwwww ); lyweight2.operation('ttttt ); lyweight3.operation('wwwww ); }

这样可以重用经常使用的对象,从而避免重新创建

三. jdk中的享元模式1.string中的享元模式String s1='hello '; String s2='hello '; String s3='he' 'llo '; stringS4='Hel'newstring('lo ); stringS5=newstring(Hello ); String s6=s5.intern (; string s7='h '; String s8='ello '; String s9=s7 s8; system.out.println(S1==S2 )//true; System.out.println (

s1==s3) // true;System.out.println(s1==s4) // false;System.out.println(s1==s9) // false;System.out.println(s4==s5) // false;System.out.println(s1==s6) // true;

为什么s1等于s2?
一看到,想当然就是等于,因为两个字符串的值是一样的嘛,但是,我们都知道到String是引用类型,s1==s2其实是地址比较,并不是值的比较。
当以字面量的形式创建String变量的时候,JVM会在编译期间就把该字面量"hello"放到字符串常量池(享元模式)中,这个字符串常量池的特点就是有且只有一份相同的字面量。如果有其他相同的字面量,JVM则返回这个字面量的引用,如果没有相同的字面量,则在字符串常量池中创建这个字面量并返回它的引用。

为什么s1等于s3?
s3中的字面量的拼接其实就是"hello",JVM在编译期间就已经对它进行了优化,所有s1等于s3

为什么s1不等于s4?
s4中new String(“lo”)生成了2个对象,这也是一道经典的面试题。"lo"存在与常量池当中,new String(“lo”)在堆当中,String s4 = “hel” + new String(“lo”);两个对象的相加存在于堆当中,而s1在常量池当中,所以不相等。
为什么s1不等于s4?
同理

为什么s4不等于s5?
都是在堆当中,一定不相等。

为什么s1等于s6?
s5.intern()方法能使一个位于堆中的字符串在运行期间动态地加入到字符串常量池当中,如果常量池中有,则返回引用。没有加入常量池,返回引用。

2.Integer 中的享元模式

看下面的例子,也是一道经典面试题

Integer a = Integer.valueOf(100); Integer b = 100; Integer c = Integer.valueOf(1000); Integer d = 1000; System.out.println(a==b); System.out.println(c==d);

运行结果:

为什么呢?
之所以会有这个结果,因为用到享元模式,我们来看下Integer类中的源码。

public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }

我们发现在IntegerCache.low和 IntegerCache.high之间的值都会取缓存。

private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int 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_VALUE h = 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() {} }

我们从源码中发现这个low=-128,high=127,然后循环将这个区间的值,放入到了缓存当中。

什么内部状态?
这些具体的区间值,127,-128,这些值是不会根据外部的使用改变的,这种就是内部状态。
什么是外部状态?
我们可以想象在线程池当中,当我们拿去一个连接的时候,这个连接就是一个“被使用”的状态,它是受外部环境改变的一个状态。这种就是外部状态。

四、优点和缺点

优点:
1.减少对象的创建,降低内存中对象的数量,降低系统内存,提高系性能。
缺点:
1.需要关注内、外部状态,关注线程安全问题(同时访问的相同的缓存)
2.系统程序负责化了(比如上面的Integer问题,不去了解,头上100个问号)

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。