关于Java equels 这个方法的问题,我的jdk卸载 程序包有问题结果为什么不对头……

关于JAVAString长度的限制
关于JAVAString长度的限制
要理解 java中String的运作方式,必须明确一点:String是一个非可变类(immutable)。什么是非可变类呢?简单说来,非可变类的实例是不能被修改的,每个实例中包含的信息都必须在该实例创建的时候就提供出来,并且在对象的整个生存周期内固定不变。java为什么要把String设计为非可变类呢?你可以问问 james Gosling :)。但是非可变类确实有着自身的优势,如状态单一,对象简单,便于维护。其次,该类对象对象本质上是线程安全的,不要求同步。此外用户可以共享非可变对象,甚至可以共享它们的内部信息。(详见《Effective java》item 13)。String类在java中被大量运用,甚至在class文件中都有其身影,因此将其设计为简单轻便的非可变类是比较合适的。  一、创建。  好了,知道String是非可变类以后,我们可以进一步了解String的构造方式了。创建一个Stirng对象,主要就有以下两种方式  java 代码  String str1 = new String("abc");  Stirng str2 = "abc";  虽然两个语句都是返回一个String对象的引用,但是jvm对两者的处理方式是不一样的。对于第一种,jvm会马上在heap中创建一个String对象,然后将该对象的引用返回给用户。对于第二种,jvm首先会在内部维护的strings pool中通过String的 equels 方法查找是对象池中是否存放有该String对象,如果有,则返回已有的String对象给用户,而不会在heap中重新创建一个新的String对象;如果对象池中没有该String对象,jvm则在heap中创建新的String对象,将其引用返回给用户,同时将该引用添加至strings pool中。注意:使用第一种方法创建对象时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 String的intern方法。看下面的例子  java 代码  String str1 = new String("abc"); //jvm 在堆上创建一个String对象  //jvm 在strings pool中找不到值为“abc”的字符串,因此  //在堆上创建一个String对象,并将该对象的引用加入至strings pool中  //此时堆上有两个String对象  Stirng str2 = "abc";  if(str1 == str2){  System.out.println("str1 == str2");  }else{  System.out.println("str1 != str2");  }  //打印结果是 str1 != str2,因为它们是堆上两个不同的对象  String str3 = "abc";  //此时,jvm发现strings pool中已有“abc”对象了,因为“abc”equels “abc”  //因此直接返回str2指向的对象给str3,也就是说str2和str3是指向同一个对象的引用  if(str2 == str3){  System.out.println("str2 == str3");  }else{  System.out.println("str2 != str3");  }  //打印结果为 str2 == str3  再看下面的例子  java 代码  String str1 = new String("abc"); //jvm 在堆上创建一个String对象  str1 = str1.intern();  //程序显式将str1放到strings pool中,intern运行过程是这样的:首先查看strings pool  //有没“abc”对象的引用,没有,则在堆中新建一个对象,然后将新对象的引用加入至  //strings pool中。执行完该语句后,str1原来指向的String对象已经成为垃圾对象了,随时会  //被GC收集。  //此时,jvm发现strings pool中已有“abc”对象了,因为“abc”equels “abc”  //因此直接返回str1指向的对象给str2,也就是说str2和str1引用着同一个对象,  //此时,堆上的有效对象只有一个。  Stirng str2 = "abc";  if(str1 == str2){  System.out.println("str1 == str2");  }else{  System.out.println("str1 != str2");  }  //打印结果是 str1 == str2  为什么jvm可以这样处理String对象呢?就是因为String的非可变性。既然所引用的对象一旦创建就永不更改,那么多个引用共用一个对象时互不影响。  二、串接(Concatenation)。  java程序员应该都知道滥用String的串接操作符是会影响程序的性能的。性能问题从何而来呢?归根结底就是String类的非可变性。既然String对象都是非可变的,也就是对象一旦创建了就不能够改变其内在状态了,但是串接操作明显是要增长字符串的,也就是要改变String的内部状态,两者出现了矛盾。怎么办呢?要维护String的非可变性,只好在串接完成后新建一个String 对象来表示新产生的字符串了。也就是说,每一次执行串接操作都会导致新对象的产生,如果串接操作执行很频繁,就会导致大量对象的创建,性能问题也就随之而来了。  为了解决这个问题,jdk为String类提供了一个可变的配套类,StringBuffer。使用StringBuffer对象,由于该类是可变的,串接时仅仅时改变了内部数据结构,而不会创建新的对象,因此性能上有很大的提高。针对单线程,jdk 5.0还提供了StringBuilder类,在单线程环境下,由于不用考虑同步问题,使用该类使性能得到进一步的提高。  三、String的长度  我们可以使用串接操作符得到一个长度更长的字符串,那么,String对象最多能容纳多少字符呢?查看String的源代码我们可以得知类String中是使用域 count 来记录对象字符的数量,而count 的类型为 int,因此,我们可以推测最长的长度为 2^32,也就是4G。  不过,我们在编写源代码的时候,如果使用 Sting str = "aaaa";的形式定义一个字符串,那么双引号里面的ASCII字符最多只能有 65534 个。为什么呢?因为在class文件的规范中, CONSTANT_Utf8_info表中使用一个16位的无符号整数来记录字符串的长度的,最多能表示 65536个字节,而java class 文件是使用一种变体UTF-8格式来存放字符的,null值使用两个字节来表示,因此只剩下 65536- 2 = 65534个字节。也正是变体UTF-8的原因,如果字符串中含有中文等非ASCII字符,那么双引号中字符的数量会更少(一个中文字符占用三个字节)。如果超出这个数量,在编译的时候编译器会报错。
H3C认证Java认证Oracle认证
基础英语软考英语项目管理英语职场英语
.NETPowerBuilderWeb开发游戏开发Perl
二级模拟试题一级模拟试题一级考试经验四级考试资料
软件测试软件外包系统分析与建模敏捷开发
法律法规历年试题软考英语网络管理员系统架构设计师信息系统监理师
高级通信工程师考试大纲设备环境综合能力
路由技术网络存储无线网络网络设备
CPMP考试prince2认证项目范围管理项目配置管理项目管理案例项目经理项目干系人管理
职称考试题目
招生信息考研政治
网络安全安全设置工具使用手机安全
生物识别传感器物联网传输层物联网前沿技术物联网案例分析
Java核心技术J2ME教程
Linux系统管理Linux编程Linux安全AIX教程
Windows系统管理Windows教程Windows网络管理Windows故障
数据库开发Sybase数据库Informix数据库
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&近期写了个电子书的C/S模式的下载工具,一个server端,一个client端。目的就是想在公司能很方便的访问家里那些收集很久电子书,方便查阅。用了1,2个星期,虽然写的很烂,但是没有用任何第三方的产品(server or db)。现在里面的书籍已经接近200本了。注:server就用了家里的adsl,所以速度慢,关闭不定时。毕竟玩玩嘛。有兴趣的朋友先装个jdk1.5。再运行下面压缩包里的exe文件执行即可。User ID:
blogjavaPassword:
Java Collection Framwork中的类的确是最重要的基础api,实现任何算法,基本上都很难离开它。
因此理解这堆“集合(Collection)类”很有必要。声明一下,以前一直都是叫它们集合类,但是好像Think In Java的作者鄙视了这个说法,严格的说应该叫Container类,而后看了它整整一章书以后,觉得还是人家说的有道理。
它说这个container类库,包含了两大类,Collection和Map,而Collection又可以分为List和Set。当然这些抽象概念都被定义成了接口。
话说,这样的分类的确是严格按照类之间的继承关系来说得,但是俺总觉得很别扭,真动手的时候,还是很难选择。当然,Anytime and Anywhere使用ArrayList绝对都能解决问题,但这样做毕竟太农民了一点。
所以,我自己有了一些想法。先回归到最基本最基本的数据结构的层面,管你是Collection还是Container,反正描述的都是一堆东西吧。数据结构第一章讲了一个结构:在物理上连续分配空间的顺序结构,叫顺序表(希望记性是好的),而离散分配空间的,应该叫做链表,最常用的就是单链表。这两个东西,其实就是很多复杂数据结构的基础,还记得吗,当时就是讲完这些东西,才开始讲栈、队列、二叉树、有向无向图的。所以,这个顺序结构是很基础的。而在JAVA中,顺序表对应的就是List接口,而一般顺序表就是ArrayList(有效进行随机index查找);而单链表就是LinkedList(有效进行插入和删除),两个的优劣当年都讲烂了,这里就不说了。
有了这两个结构以后,JAVA就不提供Stack和Queue单独的类了,因为,用户可以用上面两个类轻易的去实现。
那Set和Map有怎么跟List连上关系呢?
我认为可以把它们看成是无序和单一的List(Map只是两个有映射关系的List罢了)。
Set和Map无序和单一的特性,决定了它们天大的需求就是根据关键字(元素对象)检索。so,为了效率,必须hash。
有了HashSet和HashMap。
同时,如果非要保持住元素的顺序,有了LinkedHashSet、LinkedHashMap。
假如你的需求是1:往Container中放的对象是无序且单一的;2:经常要检索。用HashSet或HashMap吧。
ps:这两个条件其实是一回事,因为如果是不单一的话,你去检索它干嘛。
如果进而需要保持元素的顺序,不要让他顺便iteration,那就选择LinkedHashSet和LinkedHashMap。
假如你的需求不满足以上1&2,那你放心,List肯定能帮你解决,你只要稍微想一下是ArrayList好还是LinkedList好。
关于Hash,务必记得要让自己的元素对象override hashCode()和 equles() 方法,要不你直接可以洗了睡。
关于所有这些Container,务必记得有个辅助类叫Interator,遍历尽量要用它。关于一些老的Stack、Vector、HashTable,听说以后不要用了哦。收到啦!!
任何信息,基本都是以文字的形式传播和记录下来的。
在计算机中,文字就是字符的集合,也就是字符串,C就是因为对字符串设计的不好,才那么容易溢出。而别的一些高级语言,对于这个进行了很多的改进。
编程的人由于技术方向和应用方向的不同,日常编程的内容差距很大。但是对于字符串的处理,那可是永远都避不开的工作。
昨天跑步的时候,想了一下,对于字符串的操作有那么多(search,match,split,replace),感觉很烦杂,能不能抓住这些操作的一个基本集?
不知道对不对,反正想出来了一个,这个基本操作就是search,这里的search的意思是:在输入串中找到目标串的开始位置(start index),和结束位置(end index)。
有了这个基本集,别的操作都很好衍生出来:
局部match:其实就是要求search操作至少返回一个start index。
全match:其实要求search操作的至少返回一个start index,并且start index要为零,end index要为输入串的全长。
split:其实就是search操作之后,把前一个end index和当前的start index之间的字符串截出来而已。
replace:其实就是search操作之后,把start index和end index之间的字符串换成另外的而已。
所以,归根到底,都是一个search操作的拓展罢了。这么一想,感觉清晰多了。
这么一来,API对search的能力支持的好坏和效率高低是衡量字符串操作功能的标准,当然,如果有直接支持match,split,replace操作的话就更好了。
java对字符串search的支持,最基本的就是下面的String的indexOf方法:
int indexOf(String str)
Returns the index within this string of the first occurrence of the specified substring.
这里我想说的是,很多时候我们所谓要search的目标串,根本就不是固定单一的,而是变化多样的。如果只有一两种情况,最多用两次上面的方法呗。但是有些情况是近乎不可能罗列的,例如,我们讲的代表email的字符串,我们不可能遍历它吧。
所以,需要一种能够通用表达字符串格式的语言。这就是Regular Expression(re)。
假如上面方法indexOf的str参数能支持re做为参数的话,那对于这种多样的search也可以用上面的方法了。
可惜,indexOf不支持re作为参数。so,以下就介绍java api中可以用re作为参数的字符串操作方法(参数中的regex就是re)。
---------------------&&String类的:
全match操作:boolean matches(String regex)
Tells whether or not this string matches the given regular expression.
全replace操作:String replaceAll(String regex, String replacement)
Replaces each substring of this string that matches the given regular expression with the given replacement.
首个replace操作:
String replaceFirst(String regex, String replacement)
Replaces the first substring of this string that matches the given regular expression with the given replacement.
全split操作:String[] split(String regex)
Splits this string around matches of the given regular expression.有限制数的split操作:String[] split(String regex, int limit)
Splits this string around matches of the given regular expression.
&&---------------------
可惜啊,可惜,可惜java的String类里面没有可以支持re的search方法,那如果要用re来search,只好使用java中专门的re类库。
java中的re类库主要就两个类,一个叫Pattern,顾名思义,代表re的类。一个叫Matcher类,反映当前match状况的类(如存放了当前search到的位置,匹配的字符串等等信息)。
一般在构造中,“re的表达式”作为参数传递入Pattern类,“输入串(待过滤串)”作为参数传递入Matcher类。
然后使用Matcher类的字符串search方法就可以了。Matcher真正提供search功能的API叫find。下面列出。---------------------&&Matcher类search操作相关的方法:
boolean lookingAt()
Attempts to match the input sequence, starting at the beginning, against the pattern.
boolean matches()
Attempts to match the entire input sequence against the pattern.
boolean find()
Attempts to find the next subsequence of the input sequence that matches the pattern.
String group()
Returns the input subsequence matched by the previous match.
&&---------------------
前三个都是search方法,返回成功与否。第四个是返回当前search上的字符串。ok,至此。使用re的search操作也有眉目了。
当然,Pattern和Matcher也包含直接使用re进行的match,split,replace操作。
---------------------&&Patter类别的字符串操作方法
全match操作:static boolean matches(String regex, CharSequence input)
Compiles the given regular expression and attempts to match the given input against it.
全split操作:String[] split(CharSequence input)
Splits the given input sequence around matches of this pattern.
有限制数的split操作:String[] split(CharSequence input, int limit)
Splits the given input sequence around matches of this pattern.
Matcher类别的字符串操作方法
全replace操作:String replaceAll(String replacement)
Replaces every subsequence of the input sequence that matches the pattern with the given replacement string.
首个replace操作:String replaceFirst(String replacement)
Replaces the first subsequence of the input sequence that matches the pattern with the given replacement string.
动态replace(replacement可以根据被替代的字符串变化而变化)Matcher appendReplacement(StringBuffer sb, String replacement)
Implements a non-terminal append-and-replace step.
StringBuffer appendTail(StringBuffer sb)
Implements a terminal append-and-replace step.
&&---------------------总结:当必须使用re的时候,search操作就要用到Pattern,Matcher,当然动态的replace操作也要用到这两个类。而别的match,replace,split操作,可以使用pattern,Matcher,当然也可以直接使用String,推荐还是用回咱们的String吧。注:以上都是看jdk1.4以上的文档得出的结论,以前版本不能用不负责任。
创建和销毁对象
重点关注对象的创建和销毁:什么时候、如何创建对象,什么时候、什么条件下应该避免创建对象,如何保证对象在合适的方式下被销毁,如何在销毁对象之前操作一些必须的清理行为。
尝试用静态工厂方法代替构造器
要实例化一个对象来使用,傻
都知道应该先调用类的构造器来
一个对象,之后再调用相应的方法。除了这个方式,
Java Effective
还建议了另一种方法:用静态工厂方法来提供一个类的实例。以下的例子不反映两者的优劣,只是反映两者在代码实现上的不同,优劣之后再谈:
假设咱们要一个颜色为黑色、长度为
的锤子,自然就用构造器创建一个
Hammer myHammer =
new Hammer(Color.BLACK, 50);
而用静态工厂方法来实例化一个对象,如下
Hammer myHammer = Hammer.factory(Color.BLACK,50);
也可以用专门的一个工厂类来实例化
Hammer myHammer = Toolkit.factory(“Hammer”, Color.BLACK,50);
单纯从上面的代码上看,真的只有傻
才会选择静态工厂的方法,完全就是多此一举,直接
又快又爽,搞这么麻烦做莫斯(武汉话“什么”的意思)?
别急,别急,你急个莫
(武汉粗话:基本就是“你急个毛”的意思)?
下面就说说用静态工厂代替构造器的好处(
)和不好处(
disadvantage
第一个好处,讲你都不信,行家们认为,构造器有一个不好的地方就是:这个方法的签名(
)太固定了。
构造器的名字是固定的,生个
,构造器的名字就是
(……),唯一能变化的地方就是参数,假设我的这个锤子有两个很变态的构造需要:
:第一个参数是颜色(
型),第二个参数是锤子头的重量(
Color c, int kg
//remainder omited
:第一个参数是颜色(
型),第二个参数是锤子的长度(
Color c, int cm
//remainder omited
感觉满足需要了,但是细心一看,完了,构造器的参数列表类型重复了,肯定编译通不过,这是面向对象构造器天生的缺陷——唯一的变化就是参数,参数都分辨不了,就真的分辨不了。
而另外就算参数能分辨的了,构造器一多,它的参数一多,您根本就不知道每个参数是用来干什么的,只能去查阅文档,在您已经眼花缭乱的时候再去查文档,一个一个的对,折磨人的活。
这个时候,您就可以考虑用静态工厂方法来实例化对象了。因为静态工厂方法有一个最简单的特点就是:他有可以变化的方法名(构造器的名字变不了)。用名字的不同来代表不同的构造需要,这么简单的普通的特点在这里就是它相对于构造器的
如上面的锤子的例子可以这样:
Hammer.produceByWeight (Color c, int kg){
//remainder omited
Hammer.produceByHeight (Color c, int cm){
//remainder omited
这是不是一目了然多了。嗯,我是这样认为的。
第二个好处,“静态工厂方法不需要每次都真的去实例化一个对象”——其实这也是另一些优化方法的前提。
构造器的每次
必定会产生一个新的对象,而静态工厂方法经过一定的控制,完全可以不用每次
都生成一个新的对象。
为什么不每次都生成一个对象的原因就不必说了,因为原因太明显。这个原因就是为什么要“共享”对象的原因。
下面讲讲通常使用的两种共享具体策略,也就是具体方法了:
:单例模式的需要,一旦需要某个对象有单例的需要,必定对于这类对象的构造只能用静态工厂方法了。
模式和不变(
模式的需要,这两个模式很多时候都说一起使用的,一旦一些对象我们认为是不变的,那自然就想拿来重用,也就说共享,而
就是用来重用这些小粒度对象的。
Boolean.valueOf (boolean)
Boolean a = Boolean.valueOf (100);
Boolean b = Boolean.valueOf (100);
a,b两个引用都是指向同一个对象。
这些对象都是不变的,而
的控制就是用的
这种一个状态(如上面一个数字)对应的对象只有一个还有一个好处,就是可以直接通过比较“引用”来判断他们是否
是逻辑相等的意思),以前需要
a.equels(b)
,而一旦用“
模式和不变(
模式”后,避免了产生多余的相同对象,用
就可以达到
a.equels(b)
的目的了。这样当然优化了
performance
第三个好处,其实就是工厂方法的核心好处——我把它称为“抽象类型构造器”。它可以为我们提供一个抽象类型的实例,同时必要的隐藏了抽象类型的具体结构。这是
怎么都达不到的。
这种模式的好处其实就是面向对象的最核心的好处,抽象和具体可以分离,一旦抽象定义好了,具体的东西可以慢慢的变化,慢慢的拓展——开闭原则。
,都是描述集合类型的接口,也就是对于客户端来看,只有
这个类要认识,而实际上,实现这个接口的
是多种多样的。如果要让用户都知道这些具体实现的
,就增加了复杂度。
这时,通过一个静态工厂方法,就可以隐藏各种
的具体实现,而让
只使用返回的
对象就可以了。
这里还可以加上一些权限控制,如这些实现只要对于工厂来讲是可以访问的,不用是
的,而他们只要通过
的工厂就可以提供给用户。非常有利于代码的安全。
静态工厂方法的第一个缺点就是:使用静态工厂方法创建的类的构造器经常都是非公共或非
这样,以后这些类就没有办法被继承了。不过也有人说,不用继承就用
呗。也是!呵呵。
静态工厂方法的第二个缺点是:在
文档里,这些静态工厂方法很难跟别的静态方法相区别。
而文档中,构造器是很容易看到的。
为了一定程度解决这个问题,我们可以用一些比较特别的名字来给这类静态工厂方法来命名。最常用的有:
用来放回跟参数“相同值”的对象。
返回一个对象的实例。单例模式中,就是返回单例对象。
总结:静态工厂方法和构造器都有各自的特点。最好在考虑用构造器之前能先考虑一下静态工厂方法,往往,后者更有用一点。如果权衡了以后也看不出那个好用一些,那就用构造器,毕竟简单本分多了。
&&&& 摘要: 关键字:Observer Pattern、Java Thread、Java Swing Application
1 近来的阅读
近来寒暑不常,希自珍慰。武汉天气不是狂冷,就是狂热,不时还给我整个雪花,就差冰雹了。
&
自己做的事吧,也没有什么劲儿。看看自己喜欢的东西,等着希望中的学校能给我offers(是复数),看着自己想去又不想去的公司的未来同事在群里面幻想未来的样子,别操你大...&&
昨天,以前师兄做的系统因为漏洞又被投诉,头让俺做个presentation给实验室下一级同学总结一下,避免以后再犯错。今天讲完了就放上来,存个证,以后也好翻阅沟通。不涉及主机安全、网络安全、数据库安全,只从Web应用程序的角度,整理归纳一下面临的主要安全问题。点击看大图。
这几天瞄了几本设计模式的书,没有细看具体模式啦,而是老是琢磨那些深奥无比的话。这些话经常出现在计算机的书籍中,很有禅意,也有哲理。听说,高手就喜欢写点这样的话。
还有就是细心体味了一下OO的设计原则,这些原则是凌驾于模式之上的,也就是更宏观的原则。
其中,最高指导的一个就是“开-闭”原则。别的原则,里氏代换原则、依赖倒置原则、组合/聚合复用原则和迪米特法则都是为了达到“开-闭”原则而出现的规则。
这些原则告诉我很多东西,聚焦于一点就是要“面向抽象”来做一切事情。
分析对象的时候,要多分析设计“抽象”的概念,对象之间的联系要多基于抽象的概念而不是具体,这样具体才能能够变化,这样才是开闭。用我自己的话就是要“游走于 抽象”。
这里有一个我必须记住的就是,在封装变化时候,多用聚合/组合,少用继承。在封装原子变化并且是同类型对象时才用继承,别的都尽量用聚合/组合。而且尽量不要用多级继承,多级继承一般意味着有两种变化脉络,可能的话,让两种变化脉络独立演化。很明显,一独立演化,又要聚合/组合了。
还有一个必须记住的是:运用抽象以后,客户端的使用发生了巨大的变化。不再是指那儿用那儿。而是要做更多的准备工作,因为运用抽象,本身就把具体“组合”的职责推迟到使用的阶段。那谁使用,肯定是客户端。所以,客户端的使用要革新。要习惯用工厂,习惯把一系列的抽象定具体了,并按照一定方式“组合”起来用。而且,最终要善于用接口来调用方法。用小飞推荐的一个工具画了个图,如下:&&&&&&&&&&&&&&&&&&&&&&&MARCO ZHANG 日7:18:57
“共享”的思想
共享的idea是生活中最基本的idea,不必有意的使用,到处已经存在了。在生活中,大部分事物都是被多人多次使用的,这都是共享的实际应用。
之于OO的共享
OO中的共享,无非就是说让“对象”也能被“多人多次”(这里的“人”也无非就是进程、线程而已)使用,更详细的说,就是要让对象的生存空间更大一些,生存周期更长一些。
自己闷个儿脑子,提炼出了几个需要使用共享的环境(context),也可以说是原因吧:
1.为了保持“对象”的一致,我们需要共享。例如,“国家主席”就一个,不能多了,如果多了,难免决策混乱。
2.为了控制“对象”的存储空间,我们需要共享。毕竟,目前来说,系统的memory还是编程时最珍贵的资源。
3.为了优化“对象”的创建消耗,我们需要共享。如果,一个对象的创建过程消耗太大,系统不能支持频繁的创建,共享的使用它也是一个好主意。
而在实际的应用中,往往我并没有细想“我为什么使用共享?”,已经不自觉的就用了;如果真的认真分析起来,基于的环境也是多样,并不会只是上面的其中一种。
常用的“共享”方法或模式(我曾经用过的,知道的不多,望谅解):
1.“Singleton模式”:一个class就一个对象实例,大家都用它,满足context1。
2.“pool技术”:只提供一定数目的对象,大家都用他们,实现context2、context3。
3.“flyweight模式”:一个class的一个状态就一个对象实例,实现一个状态对象的共享,实现context2、context3。
使用时要注意的地方:
1.确定共享的scope。例如,在Java Web Application中就是选择是page,session还是application,当然也可以是jvm级别的static。
2.确认thread safe。当共享的对象可能被多个线程共享时,这是不可以回避的问题。
3.应对对象状态的变化。一旦共享的对象发生了变化,我们怎么处理?改变之,舍弃之?也是我们需要确定的。
项目中的应用:
项目需求:
为学校的同学提供Web查询,查询的内容有很多。其中,“查课表”、“查考表”是最为关键的需求,以后可能还要提供“查询空闲自习教室”的功能。
在这些查询中,有一个共同点,就是都涉及“教室”这一对象。“查课表”时要告诉同学在哪个教室上课,“查考表”时要告诉同学在哪个教室考试,等等。
数据库设计:
对于“查课表”用例,有关的数据库设计如下:&
对象层的设计:
学生每查询一门课程的课表,系统就会sql查询“视图V_LESSONSCHEDULE”,进而生成一个LessonSchedule对象,然后返回给用户显示。当然,在生成这个LessonSchedule对象的过程中,属于它的Classroom对象,以及更深一步的Building、Area对象都会生成。下面就是这个过程的顺序图:
因此,每生成一个“课表”对象(LessonSchedule)或“考表”对象(ExamSchedule)时,都要:
1.查数据库中的教室、教学楼、校区的信息;
2.创建相应的“教室对象”(包括了属于它的“教学楼”对象和“校区”对象)。
考虑共享“教室”对象
“教室”对象一旦可以生成以后,完全可以给后续共享使用,不必要每个查询都要去生成。
详细说是基于下面的考虑:
1.这类查询用例(查课表,查考表)发生的频繁很高很高,也就是说,一旦让用户查起来,系统中会产生大量的“教室”对象这类对象,应该说会占很大的内存空间。
2.共享“教室”对象后,可以减少对数据库的查询次数,并降低了查询粒度(以前是基于二级视图查询,现在可以基于基本表查询),提高了一点数据库查询性能。
ClassroomBuildingArea
scopewebscopeapplicationstatic
thread safeservlet
&1//取得编号为32号课程的“课表对象”&2&3LessonSchedule&oneLesson&=&LessonSchedule.findByLessonNum(<SPAN style="COLOR: #);&4&5&&6&7//获得教室对象&8&9Classroom&oneClassroom&=&oneLesson.getLnkClassroom();<SPAN style="COLOR: #<SPAN style="COLOR: #&<SPAN style="COLOR: #<SPAN style="COLOR: #//获得教学楼对象<SPAN style="COLOR: #<SPAN style="COLOR: #Building&oneBuilding&=&oneClassroom.getLnkBuilding();<SPAN style="COLOR: #<SPAN style="COLOR: #&<SPAN style="COLOR: #<SPAN style="COLOR: #//获得校区对象<SPAN style="COLOR: #<SPAN style="COLOR: #Area&oneArea&=&oneBuilding.&getLnkArea();<SPAN style="COLOR: #<SPAN style="COLOR: #&<SPAN style="COLOR: #<SPAN style="COLOR: #//再次重新生成一个编号为32号的“课表对象”<SPAN style="COLOR: #<SPAN style="COLOR: #LessonSchedule&twoLesson&=&LessonSchedule.findByLessonNum(<SPAN style="COLOR: #);<SPAN style="COLOR: #<SPAN style="COLOR: #&<SPAN style="COLOR: #<SPAN style="COLOR: #//获得教室对象<SPAN style="COLOR: #<SPAN style="COLOR: #Classroom&twoClassroom&=&twoLesson.getLnkClassroom();<SPAN style="COLOR: #<SPAN style="COLOR: #&<SPAN style="COLOR: #<SPAN style="COLOR: #//获得教学楼对象<SPAN style="COLOR: #<SPAN style="COLOR: #Building&twoBuilding&=&twoClassroom.getLnkBuilding();<SPAN style="COLOR: #<SPAN style="COLOR: #&<SPAN style="COLOR: #<SPAN style="COLOR: #//获得校区对象<SPAN style="COLOR: #<SPAN style="COLOR: #Area&twoArea&=&twoBuilding.&getLnkArea();<SPAN style="COLOR: #
oneClassroomtwoClassroomoneBuildingtwoBuildingoneAreatwoArea32
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&MARCO ZHANG 日13:48:49
||servlet&&servlet
OOservletvalidator
77overridevalidate
servletClientServlet
<SPAN style="COLOR: #//new对应的Validator接口的子类。<SPAN style="COLOR: #//这里是学生或教师可访问,因此要new&Student_Or_Teacher_Validator<SPAN style="COLOR: #Validator&validator&=&new&Student_Validator();<SPAN style="COLOR: #//然后调用验证方法就可以了<SPAN style="COLOR: #boolean&ok&=&validator.validate();
Validatorvalidate
AndRelationAndOr
3Or_StudentOr_TeacherOr_Guest3
Student_Or_Teacher_ValidatorOr_StudentOr_TeacherOr
<SPAN style="COLOR: #Validator&validator&=&new&Or_Student(new&Or_Teacher(OrRelation(req)));
Guest_Or_Student_Or_Teacher_ValidatorOr_StudentOr_TeacherOr&_GuestOr
<SPAN style="COLOR: #Validator&validator&=&new&Or_Student(new&Or_Teacher(new&Or_Guest(OrRelation(req))));
Or_Teacher
&&&&&&&&&&&&&&&&&MARCO ZHANG 日23:49:56
说起这个工厂模式,一时还真不知道该如何说起。反正这是我的开发日志,不提理论的东西,理论的东西那里都有,我只想把具体实践记录下来给师弟师妹们作个参考,积累点经验。所有这些文字都是集中讲一点――“在什么情况下为什么用某种模式好,为什么好,为什么在那种情况下能想起来用?”。
&&&&&& “针对接口编程”
2.接口和具体类的矛盾
ClientStudentStudent
ClientStudentClient
Student marco = new Small_Student();
&&&&&& ClientStudentSmall_Student
3.找“人”帮我去创建“接口对象”
ClientStudent
ClientStudent2
&&&&&& Student_Factory
&&&&&& 2这个“帮手”不符合“开-闭原则”
Version2)让“帮手”也多态
Client&&&&&&& //创建一个小学生工厂类这个帮手<SPAN style="COLOR: #&&&&&&&&Student_Factory&factory&=&new&Small_Student_Factory();<SPAN style="COLOR: #&&&&&&&&//求助这个帮手,帮我创建一个<SPAN style="COLOR: #&&&&&&&&Student&primaryStudent&=&factory.produce();<SPAN style="COLOR: #&&&&&&&&//这时就可以使用这个小学生了,让它玩玩游戏吧<SPAN style="COLOR: #&&&&&&&&primaryStudent.playGames();<SPAN style="COLOR: #
nClientSmall_StudentClientStudentStudent
nStudent_FactoryClientStudent_Factory
&&&&&& &&&&&& OO
Ent_ShiftStudent
&&&&&& Bean_ShiftStudent_Factory
&&&&&& &&&&&&&&//声明申请单接口&2&&&&&&&&Ent_Shift&es&=&null;&3&&&&&&&&//声明申请单工厂接口&4&&&&&&&&Bean_Shift&bs&=&null;&5&&&&&&&&//根据传入的申请单类型数字身成对应的申请单工厂&6&&&&&&&&switch&(shiftTypeID)&{&7&&&&&&&&&&&&case&Bean_Shift.SHIFT_CHANGETEAAP&:&8&&&&&&&&&&&&&&&&bs&=&new&Bean_Shift_CHANGETEAAP();&9&&&&&&&&&&&&&&&&break;<SPAN style="COLOR: #&&&&&&&&&&&&case&Bean_Shift.SHIFT_RESERVEAP&:<SPAN style="COLOR: #&&&&&&&&&&&&&&&&bs&=&new&Bean_Shift_RESERVEAP();<SPAN style="COLOR: #&&&&&&&&&&&&&&&&break;<SPAN style="COLOR: #&&&&&&&&&&&&case&Bean_Shift.SHIFT_RENEWAP&:<SPAN style="COLOR: #&&&&&&&&&&&&&&&&bs&=&new&Bean_Shift_RENEWAP();<SPAN style="COLOR: #&&&&&&&&&&&&&&&&break;<SPAN style="COLOR: #&&&&&&&&&&&&&//省略了别的申请单……………………<SPAN style="COLOR: #&&&&&&&&&&&&default&:<SPAN style="COLOR: #&&&&&&&&&&&&&&&&this.forwardErr(req,&resp,&"所选择的异动类别不存在");<SPAN style="COLOR: #&&&&&&&&}20<SPAN style="COLOR: #&&&&&&&&try&{<SPAN style="COLOR: #&&&&&&&&&&&&//调用工厂接口的生产方法<SPAN style="COLOR: #&&&&&&&&&&&&es&=&bs.getBlankShift(stuID);<SPAN style="COLOR: #&&&&&&&&&&&&<SPAN style="COLOR: #&&&&&&&&}&catch&(Exception&e)&{<SPAN style="COLOR: #&&&&&&&&&&&&this.forwardErr(req,&resp,&DB_ERROR);<SPAN style="COLOR: #&&&&&&&&}<SPAN style="COLOR: #&&&&&&&&//调用单子的提交方法<SPAN style="COLOR: #&&&&&&&&es.submit(req);<SPAN style="COLOR: #&&&&&&&&<SPAN style="COLOR: #&&&&&&&&//发给页面去显示<SPAN style="COLOR: #&&&&&&&&es.fowrardWithSessionObject(<SPAN style="COLOR: #&&&&&&&&&&&&&&&&req,<SPAN style="COLOR: #&&&&&&&&&&&&&&&&resp,<SPAN style="COLOR: #&&&&&&&&&&&&&&&&Ent_Shift.nameInSessionAndRequest);<SPAN style="COLOR: #
&&&&&& Design Pattern Explained
&&&&&& newnew
&&&&&& Bnewnew
&&&&&& Client
&&&&&& Ignore how they were created

我要回帖

更多关于 微信小程序缓存问题 的文章

 

随机推荐