单例 Singleton

单例 Singleton 静态内部类 static nested class 这种方法也是《Effective Java》上所推荐的。 这种写法仍然使用JVM本身机制保证了线程安全问题;由于 SingletonHolder 是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的;同时读取实例的时候不会进行同步,没有性能缺陷;也不依赖 JDK 版本。 这是利用了JVM的特性:静态内部类时在类加载时实现的,因此不会受到多线程的影响,自然也就不会出现多个实例。 public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton() { } public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } } 单例模式 (Singleton) 介绍: 也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。 实现单例模式的思路是: 一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法 (必须是静态方法,通常使用getInstance这个名称); 当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。 注意事项: 单例模式在多线程的应用场合下必须小心使用。如果当唯一实例尚未创建时,有两个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自创建了一个实例,这样就有两个实例被构造出来,从而违反了单例模式中实例唯一的原则。 解决这个问题的办法是为指示类是否已经实例化的变量提供一个互斥锁(虽然这样会降低效率)。 实现方式: 通常单例模式在Java语言中,有两种构建方式: 饿汉方式:指全局的单例实例在类装载时构建。(一般认为这种方式要更加安全些) ...

2012-10-16 · 2 min · 278 words · -

UML 类的关系: 关联,聚合,组合的区别

UML 中关联,聚合,组合的区别 关联 Association 聚合 Aggregation Composition 类间关系 在类图中,除了需要描述单独的类的名称、属性和操作外,我们还需要描述类之间的联系,因为没有类是单独存在的,它们通常需要和别的类协作,创造比单独工作更大的语义。在 UML 类图中,关系用类框之间的连线来表示,连线上和连线端头处的不同修饰符表示不同的关系。类之间的关系有继承 (泛化) 、关联、聚合和组合。 关联 (Association) 关联指的是模型元素之间的一种语义联系,是类之间的一种很弱的联系。关联可以有方向,可以是单向关联,也可以是双向关联。可以给关联加上关联名来描述关联的作用。关联两端的类也可以以某种角色参与关联,角色可以具有多重性,表示可以有多少个对象参与关联。可以通过关联类进一步描述关联的属性、操作以及其他信息。关联类通过一条虚线与关联连接。对于关联可以加上一些约束,以加强关联的含义。 class A: pass class B: def func_0(a:A) # 一个类作为另一个类方法的参数 聚合 (aggregation) 指的是整体与部分的关系。通常在定义一个整体类后,再去分析这个整体类的组成结构。从而找出一些组成类,该整体类和组成类之间就形成了聚合关系。例如一个航母编队包括海空母舰、驱护舰艇、舰载飞机及核动力攻击潜艇等。需求描述中"包含"、“组成”、“分为…部分"等词常意味着聚合关系。 在聚合中,所包含的类并不强烈依赖于容器的生命周期。在同一示例中,即使图书馆解散,书籍仍将保留。 聚合使用一个带有 空心菱形 的箭头表示,菱形指向"整体"类。 class School class Student Student --o School 组合 (composition) 也表示类之间整体和部分的关系,但是组合关系中部分和整体具有统一的生存期。一旦整体对象不存在,部分对象也将不存在。部分对象与整体对象之间具有共生死的关系。 组合使用一个带有 实心菱形 的箭头表示,菱形指向"整体"类。 class Person class Heart Heart --* Person 聚合和组合的区别在于: 聚合关系是"has-a"关系,组合关系是"contains-a"关系;聚合关系表示整体与部分的关系比较弱,而组合比较强;聚合关系中代表部分事物的对象与代表聚合事物的对象的生存期无关,一旦删除了聚合对象不一定就删除了代表部分事物的对象。组合中一旦删除了组合对象,同时也就删除了代表部分事物的对象。 我们用浅显的例子来说明聚合和组合的区别。"国破家亡",国灭了,家自然也没有了,"国"和"家"显然也是组合关系。而相反的,计算机和它的外设之间就是聚合关系,因为它们之间的关系相对松散,计算机没了,外设还可以独立存在,还可以接在别的计算机上。在聚合关系中,部分可以独立于聚合而存在,部分的所有权也可以由几个聚合来共享,比如打印机就可以在办公室内被广大同事共用。 在C++语言中,从实现的角度讲,聚合可以表示为: class A {...} class B { A* a; .....} 即类B包含类A的指针; 而组合可表示为: class A{...} class B{ A a; ...} 即类B包含类A的对象。 准确的UML类图中用空心和实心菱形对聚合和组合进行了区分。 关联和聚合的区别主要在语义上,关联的两个对象之间一般是平等的,例如你是我的朋友,聚合则一般不是平等的,例如一个公司包含了很多员工,其实现上是差不多的。聚合和组合的区别则在语义和实现上都有差别,组合的两个对象之间其生命期有很大的关联,被组合的对象是在组合对象创建的同时或者创建之后创建,在组合对象销毁之前销毁。一般来说被组合对象不能脱离组合对象独立存在,而且也只能属于一个组合对象,例如一个文档的版本,必须依赖于文档的存在,也只能属于一个文档。聚合则不一样,被聚合的对象可以属于多个聚合对象,例如一个员工可能可以属于多个公司。 我想举个通俗的例子。 你和你的心脏之间是composition关系 (心脏只属于你自己) 你和你买的书之间是aggregation关系 (书可能是别人的) 你和你的朋友之间是assoc 继承 (Extension) 指的是一个类 (称为子类) 继承另外的一个类 (称为基类) 的功能,并增加它自己的新功能的能力,继承是类与类之间最常见的关系。 ...

2012-10-15 · 5 min · 970 words · -

out of the box

out of the box out of the box: “Out of box"用于描述某种不确定的事件。常常作为副词来形容某种观点的不确定性。据说这个词同20世纪早期的英国数学家亨利?恩斯特?杜德耐解答一个著名数学谜语的思路相关。题目要求用四条直线连接平面上三乘三分布的九个点,要求一笔连成,也就是在画线的时候笔不能离开纸面。解决这个数学问题的关键在于要克服传统的在三乘三边界内画点的思想,如果将线连接到边界之外,那么问题可以迎刃而解,这样就产生了"Out of box"这个词。相应的,将思维受限这种情况称为"boxed-in”。在IT领域,节奏变化很快,因此每个人都在寻找"Out of box"的思维方式,尝试创新。 用"In the box"表示某种确定的事情。比如,最近有一篇文章讨论了MP3以及盗版音乐的关系,其中引用了一位业内人士的话表示: “主流唱片公司很少关心互联网上的发展,他们的思维就是’Inside the box’"。 “Out of the box”(开箱即用)也用作"off the shelf” (现货供应) 的同义词,其含义是指能够满足一定需求的、已经作好了的软件、硬件或两者的结合形式。如不采用,就需要投入专门的人力物力来开发。 out-of-the-box具有"创造性的,独特性,思维不合常规"的意思,但在计算机术语里又可以指"从盒子里拿出来直接可以使用的,也就是即开即用"的意思。“out-of-the-box” is similar to “off-the-shelf”, usually referinng to software/hardware which can be used as is, not requiring extra customisation or add-on components.

2012-10-15 · 1 min · 51 words · -

多普勒效应

多普勒效应 多普勒效应是为纪念奥地利物理学家及数学家克里斯琴·约翰·多普勒 (Christian Johann Doppler) 而命名的,他于1842年首先提出了这一理论,主要内容为: 物体辐射的波长因为波源和观测者的相对运动而产生变化。在运动的波源前面,波被压缩,波长变得较短,频率变得较高 (蓝移_blue shift_) ;当运动在波源后面时,会产生相反的效应。波长变得较长,频率变得较低 (红移_red shift_) ;波源的速度越高,所产生的效应越大。根据波红 (蓝) 移的程度,可以计算出波源循着观测方向运动的速度。 恒星光谱线的位移显示恒星循着观测方向运动的速度,除非波源的速度非常接近光速,否则多普勒位移的程度一般都很小。所有波动现象都存在多普勒效应. 1842年奥地利一位名叫多普勒的数学家、物理学家。一天,他正路过铁路交叉处,恰逢一列火车从他身旁驰过,他发现火车从远而近时汽笛声变响,音调变尖,而火车从近而远时汽笛声变弱,音调变低。他对这个物理现象感到极大兴趣,并进行了研究。发现这是由于振源与观察者之间存在着相对运动,使观察者听到的声音频率不同于振源频率的现象。这就是频移现象。因为,声源相对于观测者在运动时,观测者所听到的声音会发生变化。当声源离观测者而去时,声波的波长增加,音调变得低沉,当声源接近观测者时,声波的波长减小,音调就变高。音调的变化同声源与观测者间的相对速度和声速的比值有关。这一比值越大,改变就越显著,后人把它称为"多普勒效应"。

2012-10-15 · 1 min · 17 words · -

VTune

VTune 英特尔VTune™ 性能分析器 英特尔VTune™ 性能分析器可通过图形用户界面轻松优化应用性能,而且无需重新编译。它独立于编译器和语言,因此可与 C、C++、Fortran、C#、Java、.NET 等等†一起使用。与只提供调用图分析或一组有限的采样事件的产品不同,VTune 分析器可通过一组丰富的适用于所有最新英特尔® 处理器的调试事件同时实现上述两种功能。 开发出在运行 Microsoft Windows Vista*、Windows* XP 或 Windows Server* 的最新 64 位多核系统上运行如飞的软件。无需重新编译,并且只需极低的开销 (不到 5%) ,便可以确定性能瓶颈。使用图形界面与强大的 Visual Studio* 与 .NET 集成功能来分析结果。快速探查源代码,确定存在问题的代码行。 优化多核性能 内含英特尔线程档案器!对应用进行线程处理后并没有达到您预期的效果?英特尔线程档案器可帮助您调试多线程代码,从而在当今的多核处理器上取得最佳性能。 英特尔VTune™ 性能分析器 Linux* 版是完全基于 Linux 的解决方案,无论是在单核系统上还是在多核系统上,要使您的软件以最快速度运行,该解决方案都是不可或缺的。无需重新编译,也无需通过超级计算机系统在手持设备上链接,它便能分析应用程序。它功能强大,可处理大型应用程序 (源代码超过 1 GB) ,并支持多核多处理器以及使用最新英特尔处理器的 NuMA 系统。

2012-10-15 · 1 min · 42 words · -

GNU profiler

GNU profiler 各种软件对于性能的需求可能会有很大的区别,但是很多应用程序都有非常严格的性能需求,这一点并不奇怪。电影播放器就是一个很好的例子: 如果一个电影播放器只能以所需要速度的 75% 来播放电影,那么它几乎就没什么用处了。 其他应用程序 (例如视频编码) 如果是耗时非常长的操作,最好以 “批处理” 任务的方式运行,此时启动一个作业,让其一直运行,然后我们就可以去干别的事情了。尽管这些类型的应用程序没有这种硬性性能指标的限制,但是提高速度仍然会带来很多好处,例如可以在给定的时间内可以对更多电影进行编码,在同样的时间内可以以更高的品质进行编码。 通常,除了最简单的应用程序之外,对于其他应用程序来说,性能越好,这个应用程序的用处就越大,也就会越流行。由于这个原因,性能考虑是 (也应该是) 很多应用程序开发人员脑袋中的第一根弦。 不幸的是,很多尝试让应用程序速度更快的努力都白费了,因为开发人员通常都是对自己的软件进行一些_小型的优化_,而没有去研究程序在更大的范围内是如何操作的。例如,我们可能会花费大量的时间来让某个特定函数的运行速度达到原来的两倍,这一点非常不错,但是如果这个函数很少被调用 (例如打开文件) ,那么将这个函数的执行时间从 200ms 减少到 100ms,对于整个软件的总体执行时间来说并不会有太大的影响。 有效地利用您的时间的方法是,尽量优化软件中被频繁调用的部分。例如,假设应用程序花了 50% 的时间在字符串处理函数上,如果可以对这些函数进行优化,提高 10% 的效率,那么应用程序的总体执行时间就会改进 5%。 因此,如果希望能够有效地对程序进行优化,那么精确地了解时间在应用程序中是如何花费的,以及_真实的输入数据_,这一点非常重要。这种行为就称为_代码剖析 (code profiling) _。本文将简要介绍 GNU 编译器工具包所提供的一种剖析工具,它的名字让人可以产生无限遐想,叫 GNU profiler (gprof) 。

2012-10-15 · 1 min · 36 words · -

汽车知识入门

汽车知识入门 http://www.tianya.cn/publicforum/content/cars/1/254081.shtml 汽车知识入门 MPV–MPV的全称是Multi-Purpose Vehicle,即多用途汽车。它集轿车、旅行车和厢式货车的功能于一身,车内每个座椅都可调整,并有多种组合的方式,例如可将中排座椅靠背翻下即可变为桌台,前排座椅可作180度旋转等。近年来,MPV趋向于小型化,并出现了所谓的S—MPV,S是小(Small)的意思。S-MPV车长一般在(4.2—4.3)m之间,车身紧凑,一般为(5-7)座。 SUV–SUV的全称是Sport Utility Vehicle,中文意思是运动型多用途汽车。现在主要是指那些设计前卫、造型新颖的四轮驱动越野车。SUV一般前悬架是轿车型的独立悬架,后悬架是非独立悬架,离地间隙较大,在一定程度上既有轿车的舒适性又有越野车的越野性能。由于带有MPV式的座椅多组合功能,使车辆既可载人又可载货,适用范围广。 RV–RV的全称是Recreation Vehicle,即休闲车,是一种适用于娱乐、休闲、旅行的汽车,首先提出RV汽车概念的国家是日本。RV的覆盖范围比较广泛,没有严格的范畴。从广义上讲,除了轿车和跑车外的轻型乘用车,都可归属于RV。MPV及SUV也同属RV。 皮卡–皮卡(PICK-UP)又名轿卡。顾名思义,亦轿亦卡,是一种采用轿车车头和驾驶室,同时带有敞开式货车车厢的车型。其特点是既有轿车般的舒适性,又不失动力强劲,而且比轿车的载货和适应不良路面的能力还强。最常见的皮卡车型是双排座皮卡,这种车型是目前保有量最大,也是人们在市场上见得最多的皮卡。 CKD汽车–CKD是英文Completely Knocked Down的缩写,意思是"完全拆散"。换句话说,CKD汽车就是进口或引进汽车时,汽车以完全拆散的状态进入,之后再把汽车的全部零部件组装成整车。我国在引进国外汽车先进技术时,一开始往往采取CKD组装方式,将国外先进车型的所有零部件买进来,在国内汽车厂组装成整车。 SKD汽车–SKD是英文Semi—Knocked Down的缩写,意思是"半散装"。换句话说,SKD汽车就是指从国外进口汽车总成(如发动机、驾驶室、底盘等),然后在国内汽车厂装配而成的汽车。SKD相当于人家将汽车做成"半成品",进口后简单组装就成整车。 零公里汽车–零公里汽车是一个销售术语,指行驶里程为零(或里程较低,如不高于10km)的汽车,它的出现是为了满足客户对所购车辆"绝对全新"的要求。零公里表示汽车从生产线上下来后,还未有任何入驾驶过。为了保证里程表的读数为零,从生产厂到各销售点,均采用大型专用汽车运输,以保证车辆全新。 概念车–概念车由英文Conception Car意译而来。概念车不是即将投产的车型,它仅仅是向人们展示设汁人员新颖、独特、超前的构思而已。概念车还处在创意、试验阶段,很可能永远不投产。因为不足大批量生产的商品车,每一辆概念车都可以更多地摆脱生产制造水平方面的束缚,尽情地甚至夸张地展示自己的独特魅力。 概念车是时代的最新汽车科技成果,代表着未来汽车的发展方向,因此它展示的作用和意义很大,能够给人以启发并促进相互借鉴学习。因为概念车有超前的构思,体现了独特的创意,并应用了最新科技成果,所以它的鉴赏价值极高。 世界各大汽车公司都不惜巨资研制概念车,并在国际汽车展上亮相,一方面了解消费者对概念车的反映,从而继续改进;另一方面也是为了向公众显示本公司的技术进步,从而提高自身形象。 老爷车–老爷车也叫古典车,一般指20年前或更老的汽车。老爷车是一种怀旧的产物,是人们过去曾经使用的,现在仍可以工作的汽车。 老爷车这一概念始于20世纪70年代,最早出现在英国的一本杂志上,这种说法很快得到老爷车爱好者的认同。不到10年功夫,关注老爷车的人就越来越多,致使老爷车的身价戏剧性地增长起来。例如,一辆1933年款式的美国求盛伯格汽车在拍卖行卖到100万美元,一辆布加迪老爷车卖到650万美元。 零排放汽车–零排放汽车是指不排出任何有害污染物的汽车,比如太阳能汽车、纯电动汽车、氢气汽车等。有时人们也把零排放汽车称为绿色汽车、环保汽车、生态汽车、清洁汽车等。 电动汽车–目前人们所说的电动汽车多是指纯电动汽车,即是一种采用单一蓄电池作为储能动力源的汽车。它利用蓄电池作为储能动力源,通过电池向电机提供电能,驱动电动机运转,从而推动汽车前进。从外形上看,电动汽车与日常见到的汽车并没有什么区别,区别主要在于动力源及其驱动系统。 混合动力汽车–混合动力汽车就是在纯电动汽车上加装一套内燃机,其目的是减少汽车的污染.提高纯电动汽车的行驶里程。混合动力汽车有串联式和并联式两种结构形式。 燃气汽车–燃气汽车主要有压缩天然气汽车(简称LPG汽车或LPGV)和压缩天然气汽车(简称CNG汽车或CNGV)。顾名思义,LPG汽车是以液化石油气为燃料,CNG汽车是以压缩天然气为燃料,燃气汽车的CO排放量比汽油车减少90%以上,碳氢化合物排放减少70%以上,氮氧化合物排放减少35%以上,是目前较为实用的低排放汽车。 手动变速器 (MT) 手动变速器,也称手动挡,即用手拨动变速杆才能改变变速器内的齿轮啮合位置,改变传动比,从而达到变速的目的。 自动变速器 (AT) 自动变速器,利用行星齿轮机构进行变速,它能根据油门踏板程度和车速变化,自动地进行变速。而驾驶者只需操纵加速踏板控制车速即可。一般来讲,汽车上常用的自动变速器有以下几种类型: 液力自动变速器、液压传动自动变速器、电力传动自动变速器、有级式机械自动变速器和无级式机械自动变速器等。其中,最常见的是液力自动变速器。 无级变速器 (CVT) 无级变速器是由两组变速轮盘和一条传动带组成的。因此,其比传统自动变速器结构简单,体积更小。另外,它可以自由改变传动比,从而实现全程无级变速,使汽车的车速变化平稳,没有传统变速器换挡时那种"顿"的感觉。 手自一体变速器 手自一体变速器由德国保时捷车厂在911车型上首先推出,称为Tiptronic,它可使高性能跑车不必受限于传统的自动挡束缚,让驾驶者也能享受手动换挡的乐趣。此型车在其挡位上设有"+"、"-“选择挡位。在D挡时,可自由变换降挡 (-) 或加挡 (+) ,如同手动挡一样。驾驶者可以在入弯前像手动挡般的强迫降挡减速,出弯时可以低中挡加油出弯。现在的自动挡车的方向盘上又增加了”+"、"-“换挡按钮,驾驶者就能手不离开方向盘加减挡。 手动与自动主要有三方面的区别: 一是操控方式不同。手动档需要驾驶者配合离合器进行换档操作,自动档则由变速箱根据设定的传动比来操作,不需要人工干预。 二是驾驶感觉不同。手动档强调人的主观能动性,能充分唤起驾驶者的驾驶欲望和某种成就感。自动档则没有什么驾驶乐趣,讲究实用、省力。 三是油耗不同。相同品牌、排量的汽车,手动档车比自动档车省油10%左右。 AT也就是常说的自动档,MT就是手动档。在游戏默认为自动档,可以通过选项中的进行调整。那么他们有什么区别呢?简单的说,AT车换档全由车辆自己控制,MT需要人工干预。所以自动档的车开起来比较方便。自动档的汽车有很诱人的优点,首先是不用操所离合器。手动档的汽车要开好,关键是油离的配合,弄不好还会造成车辆损坏,而自动档的车,只要放到D档,驾驶者就只需要考虑油门和刹车了。再有的好处就是上坡起步不会失误,坡起一直是新手的难关,油离刹要全面的配合,常常让人手忙脚乱,而自动档的车在松开刹车准备起步时,车辆也不会后溜。 当然,自动档也有缺点。首当其从的就是动力传输效率不高,手动变速箱的机械效率大约在95%,而自动变速箱只有可怜的88%左右。另一个缺点就是制动功能,除了刹车有制动效果之外,引擎本身也有制动效果: 松开油门时,引擎的制动效果就开始发挥作用,如果从高档降入低档,制动效果更明显。 手动档的车有驾驶的乐趣,而自动档的车开起来轻松又愉快,所以现在越来越多的车开始提供自手动变速器。 车辆类型 什么是FF、FR、MR、4WD。FF: 前置引擎,前轮驱动。这种类型的车大部分机械配件都在车头,重量分配不均 (头重尾轻) ,加上转向轮和驱动轮都是前轮,容易产生转向不足。所以这种车不适合跑车,但它造价便宜,所以大部分市售车都是这种配置。FR: 前置引擎,后轮驱动。这种车具有天生的运动性能,转向灵活,甚至后有些转向过度,很多高性能的跑车都是这种配置。MR: 中置引擎,后轮驱动。相对于FF的转型不足、FR的转向过渡,MR正好适中。以运动性能而言,MR是最最理想的。不过引擎在车体中间,不但占用了空间,而且发出的噪音和热量都很容易传到车厢内,只有追求终极运动性能的跑车才会使用这种配置,如F1、又如兰博基尼。4WD: 4轮驱动。4轮驱动的车4只轮胎都有驱动力,所以他的抓地力比其他车都好,而且越野性能好,过弯稳重,这种车不限制引擎的安装位置。但4WD的车一般都很重,限制了它的动力发挥,它一般设计为拉力赛准备。AWD: 这其实也是4轮驱动,不过它特指全时4轮驱动 (All-time-4WD) ,普通的4WD只有在地牵引力时才启动4WD模式,所以也被称为分时4轮驱动。而AWD则不管什么时候都是4轮驱动模式。 马力和扭力 马力和扭力,都是引擎动力的表现。有人说"加速靠扭力,极速靠马力”。这句话其实是片面的,看完本篇你就会知道。扭力在物理学上正确的说法是扭矩,由于说成扭力的人太多,以讹传讹就变成了扭力。扭矩是推动汽车前进的根本原因。扭矩其实在初中的物理就已经学过,大致好像是这样"垂直方向的力乘上距离旋转中心点的距离",单位是 (牛顿*米) ,也可以换成公制单位 (公斤*米) 或者英制单位 (磅*英尺) 。说道汽车时,扭矩的单位一般写成"N*M/rpm",即在多少转时有多少扭矩。马力实际上也不是一种力,它是功率。引擎功率的计算也很简单: 功率(W)??2 pi × 扭矩(N-m)×转速(rpm)/60。它是衡量引擎综合表现的一个重要依据。马力在定义中是这样说的,以公制马力来讲: 一匹马于一分钟内将75公斤的物体拉动60公尺,计算得到1PS=4500kg-m/min,换算成秒1PS=75kg-m/sec,再以1W=9.8kg-m/sec来换算,得到1PS=735W。而马力又是由扭矩计算而来的,还是以公制的马力PS来说,PS=扭矩(N-m)*9.8m/sec2*rpm/716。现在,我们知道了,引擎产生了扭矩,而扭矩和转速共同作用产生了功率,而一部引擎功率的大小则是这部引擎综合能力的关键,所以"大马力决定真性能"。现在我们再回到本篇开始时的那个问题: “加速靠扭力,极速靠马力”。从公式可以知道大马力的原因是"高转速的时候仍保有高扭矩数值",也就是说要有大马力,不只是低转速的扭力要好,连高转速的扭力都得继续维持。就算在低转速时的扭矩有很大,如果没有转速的支持那轮胎依然得不到足够的转速来前进。这表示扭矩与马力的争论根本是多余的,只要能做到高马力,除了表示各转速区域的扭力都很大之外,更代表材料技术的优越性,将活塞、进排气阀门的材质与重量予以强化与轻量化,才能将引擎转速提高。说白了,这一篇讨论的就是引擎。在U2中可以给我调校的引擎参数只有ECU。ECU负责控制引擎在各个转速区域内的扭矩输出,前面已经说过引擎大马力表现的原因是高转速的时候仍保有高扭矩数值。所以,ECU在调校时可以将扭矩峰值之后的转速区域的ECU值调到最高,这样有效增加了高转速的扭矩输出,这样的车开起来会觉得动力充沛,特别是在6000转以上时,动力输出平滑而有力。 ...

2012-10-14 · 1 min · 152 words · -

Builder, Factory

Builder, Factory http://www.cnblogs.com/shenfx318/archive/2007/01/28/632724.html 在设计模式的学习过程中,Builder与Factory是创建模式中两个经典的教程,给与了我们很多值得汲取的宝贵设计思想,然而Builder与Factory模式也是初学者容易混淆的两个模式,经常看到有人问及两者的区别与适用的场景,我在近一段设计模式的学习过程中同样碰到了这个问题,在两种模式的区别与联系间我看到的更多是后者,在这里愿意与大家分享一些我对Builder与Factory模式的感悟,有说的不对的地方,还请各位多加提点、指教。 写在前面 本文旨在两种模式间的对比与探讨,因此还希望各位看官首先对两个模式有一定的了解为好,因为常常看到有人提问说,Builder模式与抽象工厂 (Abstract Factory) 之间的区别,其实在我看来这两者间并无太多联系,因此也就谈不上区别,至于原因在此不做细述,有兴趣的朋友可以看看我写的有关 http://www.cnblogs.com/shenfx318/archive/2007/01/16/621237.html 抽象工厂的文章。故本文中所提的Factory模式皆指的是工厂方法 (Factory Method) 。 从Builder到Factory的演化 先来看看Builder模式,Builder模式的一般设计及实现 ```java public interface IBuilder { void BuildPart1(); void BuildPart2(); Product GetResult(); } //ConcreteBuilderA public class BuilderA : IBuilder { private Product product; public void BuildPart1() { product = new Product(); product.Add(“Part1 build by builderA”); } public void BuildPart2() { product.Add(“Part2 build by builderA”); } public Product GetResult() { return product; } } } //ConcreteBuilderB public class BuilderB : IBuilder //Director public class Director { public void Construct(IBuilder builder) { builder.BuildPart1(); builder.BuildPart2(); } } ...

2012-10-12 · 2 min · 378 words · -

持续改进,抽象工厂也反射

持续改进,抽象工厂也反射 http://www.cnblogs.com/shenfx318/archive/2007/01/16/621237.html 在我的上一篇文章(疑惑?改良?从简单工厂到工厂方法)中,详细论述了创建模式中简单工厂到工厂方法的演变过程,并试图结合工厂方法的设计以及.net中的反射机制之所长,改良出一种新型的工厂—反射工厂,这当然不是我的首创,经典的PetShop 中便有此工厂的身影。本文尝试按照前篇文章的思路,借着工厂方法到抽象工厂的演变过程而继续对抽象工厂进行改良,文章中的思想仅代表了作者当时的观点,有欠妥的地方,还请各位不吝赐教。 工厂模式 前面的文章提到了简单工厂和工厂方法其实是一码事,他们完成了将客户对产品功能的使用与创建具体产品职责的分割,不同的只不过是他们实现方式上的差异,工厂方法利用更加优雅的多态性取代了相对ugly的switch case…语句,从而很好的体现了设计原则中的OCP原则,此文章将不再强调这种实现上的差异性,而更多的强调两者之间设计思路上的共性,并将这种共性统称成为工厂模式,从而进一步与抽象工厂进行对比。 工厂的使用,选择的过程 工厂模式的使用,实际上是客户 (产品的消费者) 对于产品选择的过程,对于实现了相同功能的产品来讲,客户更加关心的是产品间的差异性,而工厂的作用则是将产品的生产过程封装,根据客户的要求直接返回客户需要的产品。注意,工厂只是隐藏了产品的生产过程,但是并没有剥夺客户选择的权利,那么客户的这个选择过程又是如何体现的呢?在简单工厂中,客户通过参数的形式告诉工厂需要什么样的产品,而在工厂方法中,客户通过对工厂的选择代替了直接对产品的选择,注意到工厂方法中一个工厂只有一个Create方法,也就是说一个工厂只负责生产一种产品,那么你选择了相应的工厂也就等同于你选择了对应的产品。就连改良后的反射工厂也没有消去对产品的选择,只不过是将这种选择外化 (外化到配置文件中,从而使得对代码的改动最小) 。可以说,正是由于产品间的差异性带给了客户选择的权利,这种权利是不应当被工厂取代的,那么工厂模式的价值又在哪里呢?答案是抽象与封装,工厂模式将由于客户的不同选择而可能导致的对已知事物的影响降到最低,途径是通过抽象产品取代具体产品,使得客户依赖于抽象 (越抽象的东西越稳定) ,同时将客户的选择封装到一处,隔离与具体产品间的依赖。 工厂模式与抽象工厂 前面说了这么多无关的,为得是做好铺垫,更加有益于对下文的理解,OK,终于该说说从工厂模式到抽象工厂的转变了,先来对比两张类图: 工厂方法(Factory Method) <img src="http://images.cnblogs.com/cnblogs_com/shenfx318/FactoryMethod3.jpg" alt="" width="506" height="186" border="0" /> 抽象工厂(Abstract Factory) 从图中我们能够看到哪些差异? 最明显的一点就是在工厂方法的类关系图中只有一类产品,他们实现了一个统一的接口,而抽象工厂有多个类别的产品,他们分别实现了不同的功能 (多个接口) 。其次的一点差别就是工厂本身所具有的方法数量不同,这点差异其实也是由第一点所导致的,工厂需要有生产不同类别产品的功能,如果抽象工厂中的产品的功能简化到一个,也便成为了工厂方法。 引出类别的概念,类别是指具有相同功能的一类产品的总称。 再来看选择的过程,在工厂方法中,客户关心的只不过是实现同一样功能的不同产品间的差异,这是一个一维选择的过程。 1 IFactory factory = new FactoryA(); //选择了工厂即选择了产品 2 IProduct productA = factory.Create(); //工厂只有一个Create方法,只能生产一种产品 而在抽象工厂中,客户首先要考虑的是需要哪一样功能,其次要考虑才是产品间的差异。也就是说这是一个二维选择的过程。 1 IFactory factory = new FactoryA(); //选择了某个具体工厂 2 IProduct productA = factory.CreateProductA(); //工厂具有多个Create方法,这里选择了其中的一个 ...

2012-10-12 · 1 min · 202 words · -

Factory, Abstract Factory, Factory Method, 和Builder

Factory, Abstract Factory, Factory Method, 和Builder 选这4个模式在一起讨论首先是因为它们的功能比较类似,都是用来制造对象实例的,从归类来说,他们都属于制造类模式(creational patterns),其次她们们在工作中比较常用,由于功能太过相似,往往导致在某个实际问题上让人举棋不定,似乎选哪个都可以解决问题,可是真的选择某个模式后,又会发现不是完全合适。今天我们就来讨论讨论在什么情况下选择什么模式来解决问题比较合适。 考虑到不是所有的朋友都对以上提到的4种模式都了如指掌,在开始讨论之前先简单的介绍一下这4个模式,对这4种模式熟悉的朋友也可以顺便回顾一下。请注意,这里我只会做简短的介绍,如果要比较深入地了解她们的话,还请去看模式相关的书籍,比较浅显易懂的我推荐 “Head First Design Patterns”。如果要在工作中反复参考的我推荐 “Applied Java Patterns”。那本经典的GOF Design Patterns由于写的时间比较早,举的例子不太适合现在的软件开发,我个人认为初学者或者是没有太多时间的朋友没有必要去读那本书,尽管她的确是经典。 Factory Pattern 中文叫工厂模式, 这个是我们在面向对象编程中最常用的模式之一了,她的主要功能就是制造对象,也正是这个原因才叫她为工厂模式,工厂干什么?生产产品。通常情况而言某个工厂所生产的产品总是一个系列的不同种类,大体上相同,细节上有差异。 图1 展示了一个非常简单的例子,通常CarFactory类会提供下列方法来生产车辆, 如代码片断1所示: public class CarFactory { public Car createBusinessCar() {….} public Car createSportCar() {…} } 代码片断 1 http://www.wiloon.com/wp-content/uploads/2012/10/x1pBG_wmiiVq4fKhMkEoTbjopPcKCE3u0uJjfqcYoYvgBeu5PDT5UndtcNdt48rY80PV_fd8Ce5pLpHavAj520cgRoVa4EmOhjE5VNS7GnBHl126UUuSSCrcM8YMFLVb3mp_UsivKRLJ1HKESriM5FDQA-1.gif 图1 Factory Pattern Abstract Factory Pattern 中文叫抽象工厂模式,顾名思义,就是把工厂模式在进一步抽象化,进一步细化。我们继续沿用上面的例子,不过这次增加产品的种类,如图2所示。由于我们增加了一层分类,当我们要生产某种车的时候就需要询问要哪种车, 商用还是跑车?不然的话就要增加create方法,如果分类多了,create方法就会成几何数量增长。 public class CarFactory { public Car createBusinessBMWCar() {….} public Car createBusinessBenzCar() {…} public Car createSportBMWCar() {….} public Car createSportBenzCar() {…} } 代码片断 2 图2 bad Factory Pattern ...

2012-10-11 · 2 min · 236 words · -

阿贝尔群

阿贝尔群 阿贝尔群 (Abelian Group) ,又称交换群或加群,是这样一类群 (G, *): 对任意 a,b 属于 G,满足 a * b = b * a。阿贝尔群以挪威数学家尼尔斯·阿贝尔命名。由阿贝尔群分解定理, 任何阿贝尔群可以分解成一些整数群和剩余类群的直和, 这个分解是唯一的, 其中分解出来的整数群的个数称为阿贝尔群的秩。 比阿贝尔群更广泛的概念是模的概念 记号方式 可换群有两个传统的记号方式. - 加法及乘法.

2012-10-10 · 1 min · 26 words · -

JAVA 浅复制与深复制/深克隆/深拷贝

JAVA 浅复制与深复制/深克隆/深拷贝 1.浅复制与深复制概念 ⑴浅复制 (浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。 ⑵深复制 (深克隆) 被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。 2.Java的clone()方法 ⑴clone方法将对象复制了一份并返回给调用者。一般而言,clone () 方法满足: ①对任何的对象x,都有x.clone() !=x//克隆对象与原对象不是同一个对象 ②对任何的对象x,都有x.clone().getClass()= =x.getClass()//克隆对象与原对象的类型一样 ③如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。 ⑵Java中对象的克隆 ①为了获取对象的一份拷贝,我们可以利用Object类的clone()方法。 ②在派生类中覆盖基类的clone()方法,并声明为public。 ③在派生类的clone()方法中,调用super.clone()。 ④在派生类中实现Cloneable接口。 请看如下代码: class Student implements Cloneable { String name; int age; Student(String name,int age) { this.name=name; this.age=age; } public Object clone() { Object o=null; try { o=(Student)super.clone();//Object中的clone()识别出你要复制的是哪一个对象。 } catch(CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } public static void main(String[] args) { Student s1=new Student("zhangsan",18); Student s2=(Student)s1.clone(); s2.name="lisi"; s2.age=20; System.out.println("name="+s1.name+","+"age="+s1.age);//修改学生2后,不影响学生1的值。 } } 说明: ...

2012-10-09 · 2 min · 369 words · -

抽象工厂模式解析例子

抽象工厂模式解析例子 抽象工厂模式中的有以下的四种角色: 抽象工厂 (Abstract Factory) 角色: 担任这个角色的是工厂方法模式的核心,它是与应用系统业务逻辑无关的。 具体工厂 (Concrete Factory) 角色: 这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的业务逻辑紧密相关的。 抽象产品 (Abstract Product) 角色: 担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。 具体产品 (Concrete Product) 角色: 这个角色用以代表具体的产品。 抽象工厂模式就相当于创建实例对象的new,由于经常要根据类生成实例对象,抽象工厂模式也是用来创建实例对象的,所以在需要新的事例对象时便可以考虑是否使用工厂模式。虽然这样做可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。 举例来说: 生产餐具和相应食物的工厂,有两个车间,其中一个车间用以生产餐具,一个车间用以生产相应的食物。 当消费者消费时,只需要向相应的具体工厂请求具体餐具和具体食物便可以使用餐具消费食物。 每个具体工厂生产出来的具体产品根据不同工厂的不同各不相同,但是客户使用产品的方法是一致的。比如客户在得到餐具和食物之后,两者的搭配是正确的 (使用汤匙喝牛奶,使用刀子切面包) 。 在本例子中有3个具体工厂AKetchen, BKetchen, BKetchen,分别生产牛奶和汤匙、面包和刀、肉和叉子。牛奶、面包和肉都实现了食物接口。汤匙、刀和叉子都实现了餐具接口。 抽象工厂的接口定义如下所示; public interface KetchenFactory{ public Food getFood(); public TableWare getTableWare(); } //抽象餐具的接口定义如下所示: public interface TableWare{ public String getTool(); } //抽象食物的接口定义如下所示: public interface Food{ public String getEatable(); } //而具体的实现也非常简单,以AKetchen为例子 //具体工厂AKetchen的定义如下所示; public class AKetchen implements KetchenFactory{ public Food getFood(){ return new Milk(); } public TableWare getTableWare(){ return new Spoon(); } } //具体餐具(spoon)的定义如下所示: public class Spoon implements TableWare{ public String getTool() { return "spoon"; } } //具体食物(milk)的定义如下所示: public class Milk implements Food{ public String getEatable(){ return "milk"; } } //客户端的定义如下: public class Client{ public void eat(KetchenFactory k){ System.out.println("A person eat "+k.getFood().getEatable() +" with "+k.getTableWare().getTool()+"!"); } public static void main(String[] args){ Client client= new Client(); KetchenFactory kf = new AKetchen(); client.eat(kf); kf=new BKetchen(); client.eat(kf); kf= new CKetchen(); client.eat(kf); } } 小结: 抽象工厂模式特别适合于这样的一种产品结构: 产品分为几个系列,在每个系列中,产品的布局都是要同的,在一个系列中某个位置的产品,在另一个系列中一定有一个对应的产品。这样的产品结构是存在的,这几个系列中同一位置的产品可能是互斥的,它们是针对不同客户的解决方案,每个客户都只择其一。 ...

2012-10-09 · 1 min · 159 words · -

webkit

webkit WebKit 是一个开源的浏览器引擎,与之相对应的引擎有Gecko (Mozilla Firefox 等使用) 和Trident (也称MSHTML,IE 使用) 。同时WebKit 也是苹果Mac OS X 系统引擎框架版本的名称,主要用于Safari,Dashboard,Mail 和其他一些Mac OS X 程序。WebKit 前身是 KDE 小组的 KHTML,WebKit 所包含的 WebCore 排版引擎和 JSCore 引擎来自于 KDE 的 KHTML 和 KJS,当年苹果比较了 Gecko 和 KHTML 后,仍然选择了后者,就因为它拥有清晰的源码结构、极快的渲染速度。Apple将 KHTML 发扬光大,推出了装备 KHTML 改进型 WebKit 引擎的浏览器 Safari。 WebKit 所包含的 WebCore 排版引擎和 JSCore 引擎,均是从KDE的KHTML及KJS引擎衍生而来,它们都是自由软件,在GPL条约下授权,同时支持BSD系统的开发。所以Webkit也是自由软件,同时开放源代码。 WebKit的优势在于高效稳定,兼容性好,且源码结构清晰,易于维护。 尽管Webkit内核是个非常好的网页解析机制,但是由于以往微软把IE捆绑在Windows里(同样的Webkit内核的Safari捆绑在Apple产品里,Google Chrome捆绑在Google产品里),导致许多网站都是按照IE来架设的,很多网站不兼容Webkit内核,比如登录界面、网银等网页均不可使用Webkit内核。目前几乎所有网站和网银已经逐渐支持WebKit,未来可能将取代IE内核的浏览器。 WebKit 内核在手机上的应用也十分广泛,例如 Google 的手机 Android、 Apple 的 iPhone, Nokia’s Series 60 browser 等所使用的 Browser 内核引擎,都是基于 WebKit。 WebKit是开源的Web浏览器引擎,苹果的Safari、谷歌的Chrome浏览器都是基于这个框架来开发的。WebKit 还支持移动设备和手机,包括iPhone和Android手机都是使用WebKit做为浏览器的核心。 ...

2012-10-09 · 1 min · 176 words · -

浏览器加载和渲染网页的过程

浏览器加载和渲染网页的过程 关于网页加载和渲染的过程,在网络上的讨论并不多。可能是因为这个过程比较复杂,而且浏览器执行的速度太快,目前还没有发现什么比较好的工具可以清楚的看到浏览器解析网页的每一个过程。通过firedug和httpWatch可以看到浏览器的http请求,但是对于浏览器如何paint和flow处理html元素,我们仍然是不得而知。“flow"这个词借鉴于reflow,表示浏览器第一次加载网页的过程。在网络上搜索了一下,学习如下。 关于浏览器加载网页过程的有趣视频 可以参见: http://www.aoao.org.cn/blog/2008/05/reflow/ (形象化的reflow) 。这个视频展现了网页加载的过程,看着比较有趣。要是可以更加形象化,就更好了,可以帮助我们书写更好的提高网页加载速度的代码。 浏览器内核 不同的浏览器内核,对于网页的解析过程肯定也不尽相同。http://www.mac52ipod.cn/post/Trident-Gecko-WebKit-Presto.php 一文对各种浏览器的页面渲染引擎进行了简介。目前主要有基于 (1) Trident页面渲染引擎 –> IE系列浏览器; (2) Gecko页面渲染引擎 –> Mozilla Firefox; (3) KHTML页面渲染引擎或WebKit框架 –> Safafi和Google Chrome; (4) Presto页面渲染引擎 –> Opera 详细的介绍可以参见原文。 浏览器解析网页的过程 http://hi.baidu.com/seosky/blog/item/78d3394c130f86ffd72afc56.html 浏览器加载和渲染原理分析一文中通过一定的方法,推断了浏览器加载解析网页的顺序大致如下: IE下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的; 在渲染到页面的某一部分时,其上面的所有部分都已经下载完成 (并不是说所有相关联的元素都已经下载完) ; 在下载过程中,如果遇到某一标签是嵌入文件,并且文件是具有语义解释性的 (例如: JS脚本,CSS样式) ,那么此时IE的下载过程会启用单独连接进行下载,并且在下载后进行解析,解析 (JS、CSS中如有重定义,后定义函数将覆盖前定义函数) 过程中,停止页面所有往下元素的下载; 样式表文件比较特殊,在其下载完成后,将和以前下载的所有样式表一起进行解析,解析完成后,将对此前所有元素 (含以前已经渲染的) 重新进行样式渲染。并以此方式一直渲染下去,直到整个页面渲染完成。 当然这是一个推断的过程。 借助Google PageSpeed和Yahoo YSlow分析网页加载 通过这两个工具,测试网页加载过程,可以得到一些提高网页加载速度的建议。使用Google PageSpeed对Google首页进行分析,可以得到建议: (1) 压缩javascript和CSS; (2) 合并外部javascript和CSS; (3) 减少DNS寻址时间;这条与将图片分散到不同的域名存储这条折中处理; (4) 使用缓存; (5) 尽量避免CSS表达式; (6) 为图片增加宽度和高度属性; (7) 将css放在网页头部,合理放置js的位置。 同时,利用YSlow对google首页进行分析,我们也可以得到一些改进的建议。这些建议差不太多,就不在详细说明。 合理使用这两个工具,优化我们的网页,提高网页加载速度,增强用户体验。 我自己的误解 过去一直以为,一个容器如果没有读到自己的结束标签,那么这个容器就不会在浏览器中显示出来。今天测试了下,却发现浏览器在读到一个容器的开始标签的时候,就可以显示该容器了。关于浏览器如何一个一个的paint HTML中的元素,如果flow它们,这个过程还需要进一步了解。当然,也可以不管过程,只看加载的结果,通过pagespeed和Yslow来优化自己的网页。个人在做布局的时候,还是会秉承一条原则: 尽量让一个父容器小一些! 参考文献 ...

2012-10-08 · 1 min · 86 words · -

DOM, BOM

DOM, BOM BOM 浏览器对象模型 提供了独立于内容而与浏览器窗口进行交互的对象。描述了与浏览器进行交互的方法和接口,可以对浏览器窗口进行访问和操作,譬如可以弹出新的窗口,改变状态栏中的文本,对Cookie的支持,IE还扩展了BOM,加入了ActiveXObject类,可以通过js脚本实例化ActiveX对象等等) 文档结构图 BOM由以一系列相关的对象组成。下图展示了基本的BOM体系结构。 BOM中的对象 Window对象: 是整个BOM的核心,所有对象和集合都以某种方式回接到window对象。Window对象表示整个浏览器窗口,但不必表示其中包含的内容。 Document对象: 实际上是window对象的属性。这个对象的独特之处是唯一一个既属于BOM又属于DOM的对象。从BOM角度看,document对象由一系列集合构成,这些集合可以访问文档的各个部分。 Location对象: 它是window对象和document对象的属性。Location对象表示载入窗口的URL,此外它还可以解析URI. Navigator对象: Navigator包含大量Web浏览器相关的信息。各种浏览器支持该对象的属性和方法不尽相同。 Screen对象: 通过其可以获取用户屏幕相关的信息 DOM 文档对象模型 DOM是针对XML的基于树的API。描述了处理网页内容的方法和接口,是HTML和XML的API,DOM把整个页面规划成由节点层级构成的文档。 DOM本身是与语言无关的API,它并不与Java,JavaScript或其他语言绑定。 特定语言的DOM 针对XHTML和HTML的DOM。这个DOM定义了一个HTMLDocument和HTMLElement做为这种实现的基础。 其他的包括SVG的DOM 对于DOM的支持 各种浏览器对于DOM的支持不一样。 Mozila支持最好,几乎所有的DOM Level 2以及部分DOM Level 3。在 Opera和Safrai支持所有的DOM Level1和大部分DOM Level2。 IE,支持大部分的DOM Level 1。 DOM 的各种 Level DOM Level 1 包括 DOM Core 和 DOM HTML。前者提供了基于XML的文档结构图。后者添加了一些HTML专用的对象和方法,从而扩展了DOM Core. DOM Level 2 引入几个新模块: DOM视图,事件,样式,遍历和范围 DOM Level 3 引入了以统一的方式载入和保存文档的方法。DOM Core被扩展支持所有的XML1.0的特性 http://titan.iteye.com/blog/60389 DOM 事件 onblur="hanshu(this)" 获得焦点: onfocus="hanshu(this)"

2012-10-08 · 1 min · 67 words · -

java Delegate

java Delegate 委派,也可以叫做委托,从字面上来理解的话,应该是委托其他类做事情而自己不做或者只做一部分工作;而回调,就是调用自己的方法。 在 java 中,这两种机制很类似,你姑且可以认为它们就是一码事。 java 中,实现委派和回调都是通过接口来实现的。下面举个小例子吧! 该例子是这样的 (只是一个例子) : ProfessionalWorker 、SparetimeWorker 负责发射 Rocket,Rocket 类通过接口 IRocketDelegate 委派 (或者说是回调) ProfessionalWorker 、SparetimeWorker自己发射。 总之,Rocket不做具体的事情。看实例代码: IRocketDelegate.java源码 public interface IRocketDelegate { public abstract long startAtTime(); public abstract long endAtTime(); public abstract void sendDidFail(); } 共有三个方法,分别是用于计算 Rocket 发射时间、计算 Rocket 发射完毕的时间以及发送是否失败的。 Rocket.java源码 public class Rocket { IRocketDelegate delegate = null; public Rocket(IRocketDelegate delegate) { this.delegate = delegate; } private long getRocketStartTime() { long startTime = delegate.startAtTime(); return startTime; } private long getRocketEndTime() { long endTime = delegate.endAtTime(); return endTime; } public boolean isOk() { // 超时0.1秒为失败 if (getRocketEndTime() - getRocketStartTime() >= 100) { delegate.sendDidFail(); return false; } return true; } } 在这个类中,声明一个 IRocketDelegate 接口对象,使用该对象调用接口的方法。我们知道,接口不可以直接实例化,换句话说,实例化接口必须实现接口的所有方法。 ...

2012-10-08 · 2 min · 302 words · -

里氏代换原则

里氏代换原则 里氏代换原则 (Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对"开-闭"原则的补充。实现"开-闭"原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。LSP讲的是基类和子类的关系。只有当这种关系存在时,里氏代换关系才存在。如果两个具体的类A,B之间的关系违反了LSP的设计,(假设是从B到A的继承关系)那么根据具体的情况可以在下面的两种重构方案中选择一种。 –创建一个新的抽象类C,作为两个具体类的超类,将A,B的共同行为移动到C中来解决问题。 –从B到A的继承关系改为委派关系。 为了说明,我们先用第一种方法来看一个例子,第二种办法在另外一个原则中说明。我们就看那个著名的长方形和正方形的例子。对于长方形的类,如果它的长宽相等,那么它就是一个正方形,因此,长方形类的对象中有一些正方形的对象。对于一个正方形的类,它的方法有个setSide和getSide,它不是长方形的子类,和长方形也不会符合LSP。 eg: 长方形类: public class Rectangle{ … setWidth(int width){ this.width=width; } setHeight(int height){ this.height=height } } 正方形类: public class Square{ … setWidth(int width){ this.width=width; this. height=width; } setHeight(int height){ this.setWidth(height); } } 例子中改变边长的函数: public void resize(Rectangle r){ while(r.getHeight()<=r.getWidth){ r.setHeight(r.getWidth+1); } } 那么,如果让正方形当做是长方形的子类,会出现什么情况呢?我们让正方形从长方形继承,然后在它的内部设置width等于height,这样,只要width或者height被赋值,那么width和height会被同时赋值,这样就保证了正方形类中,width和height总是相等的.现在我们假设有个客户类,其中有个方法,规则是这样的,测试传入的长方形的宽度是否大于高度,如果满足就停止下来,否则就增加宽度的值。现在我们来看,如果传入的是基类长方形,这个运行的很好。根据LSP,我们把基类替换成它的子类,结果应该也是一样的,但是因为正方形类的width和height会同时赋值,这个方法没有结束的时候,条件总是不满足,也就是说,替换成子类后,程序的行为发生了变化,它不满足LSP。 那么我们用第一种方案进行重构,我们构造一个抽象的四边形类,把长方形和正方形共同的行为放到这个四边形类里面,让长方形和正方形都是它的子类,问题就OK了。对于长方形和正方形,取width和height是它们共同的行为,但是给width和height赋值,两者行为不同,因此,这个抽象的四边形的类只有取值方法,没有赋值方法。上面的例子中那个方法只会适用于不同的子类,LSP也就不会被破坏。在进行设计的时候,我们尽量从抽象类继承,而不是从具体类继承。如果从继承等级树来看,所有叶子节点应当是具体类,而所有的树枝节点应当是抽象类或者接口。当然这个只是一个一般性的指导原则,使用的时候还要具体情况具体分析。

2012-10-08 · 1 min · 53 words · -

戴森球

戴森球 戴森球[1]是一种设想中的巨型人造结构,由弗里曼·戴森先生提出。这样一个"球体"是由环绕太阳的卫星所构成,完全包围恒星并且获得其绝大多数或全部的能量输出。戴森认为这样的结构是在宇宙中长期存在并且能源需求不断上升的文明的逻辑必然,并且他建议搜寻这样的人造天体结构以便找到外星超级文明。 从那时起,各种各样的设计,包括建造人工天体或一系列这样的结构以便包围太阳,便不断地由一些狂想的工程学家或科幻小说所提出,并冠以"戴森球"之名。这些后续的设想没有仅仅在从太阳能收集站上止步-许多工程设计还包括建设人类殖民地和工业基地。 http://baike.baidu.com/view/468337.htm

2012-10-08 · 1 min · 4 words · -

图像二值化

图像二值化 就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果。 将256个亮度等级的灰度图像通过适当的阈值选取而获得仍然可以反映图像整体和局部特征的二值化图像。在数字图像处理中,二值图像占有非常重要的地位,首先,图像的二值化有利于图像的进一步处理,使图像变得简单,而且数据量减小,能凸显出感兴趣的目标的轮廓。其次,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像。 所有灰度大于或等于阀值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。

2012-09-30 · 1 min · 4 words · -