unit JvGnugettext;
http://www.delphipraxis.net/post940812.html
posted @ 2008-09-17 16:34 张树坤 阅读(21) | 评论 (0)编辑
关于调整2008年度下半年计算机技术与软件专业技术资格(水平)考试报名时间有关事宜的通知
发布日期:2008-07-02 浏览次数:5426 次

各位考生:
   2008年度下半年计算机技术与软件专业技术资格(水平)考试报名时间调整为2008年7月10日至30日、9月1日至15日。报考人员可于上述规定时间登录北京市人事考试网,按要求办理报名及缴费手续。具体操作流程及报名事宜请参考2008年度计算机技术与软件专业技术资格(水平)考试相关文件。

北京市人事考试中心
二〇〇八年七月二日

关闭窗口

http://www.bjpta.gov.cn/news_z.asp?news_id=575
posted @ 2008-07-07 13:22 张树坤 阅读(267) | 评论 (0)编辑


转 ttp://blog.csdn.net/big_worm/archive/2007/07/23/1702772.aspx

第一范式(1NF):在关系模式R中的每一个具体关系r中,如果每个属性值 都是不可再分的最小数据单位,则称R是第一范式的关系。例:如职工号,姓名,电话号码组成一个表(一个人可能有一个办公室电话 和一个家里电话号码) 规范成为1NF有三种方法:
一是重复存储职工号和姓名。这样,关键字只能是电话号码。
二是职工号为关键字,电话号码分为单位电话和住宅电话两个属性
三是职工号为关键字,但强制每条记录只能有一个电话号码。
以上三个方法,第一种方法最不可取,按实际情况选取后两种情况。

第二范式(2NF):如果关系模式R(U,F)中的所有非主属性都完全依赖于任意一个候选关键字,则称关系R 是属于第二范式的。
例:选课关系 SCI(SNO,CNO,GRADE,CREDIT)其中SNO为学号, CNO为课程号,GRADEGE 为成绩,CREDIT 为学分。 由以上条件,关键字为组合关键字(SNO,CNO)
在应用中使用以上关系模式有以下问题:
a.数据冗余,假设同一门课由40个学生选修,学分就 重复40次。
b.更新异常,若调整了某课程的学分,相应的元组CREDIT值都要更新,有可能会出现同一门课学分不同。
c.插入异常,如计划开新课,由于没人选修,没有学号关键字,只能等有人选修才能把课程和学分存入。
d.删除异常,若学生已经结业,从当前数据库删除选修记录。某些门课程新生尚未选修,则此门课程及学分记录无法保存。
原因:非关键字属性CREDIT仅函数依赖于CNO,也就是CREDIT部分依赖组合关键字(SNO,CNO)而不是完全依赖。
解决方法:分成两个关系模式 SC1(SNO,CNO,GRADE),C2(CNO,CREDIT)。新关系包括两个关系模式,它们之间通过SC1中的外关键字CNO相联系,需要时再进行自然联接,恢复了原来的关系

第三范式(3NF):如果关系模式R(U,F)中的所有非主属性对任何候选关键字都不存在传递信赖,则称关系R是属于第三范式的。
例:如S1(SNO,SNAME,DNO,DNAME,LOCATION) 各属性分别代表学号,
姓名,所在系,系名称,系地址。
关键字SNO决定各个属性。由于是单个关键字,没有部分依赖的问题,肯定是2NF。但这关系肯定有大量的冗余,有关学生所在的几个属性DNO,DNAME,LOCATION将重复存储,插入,删除和修改时也将产生类似以上例的情况。
原因:关系中存在传递依赖造成的。即SNO -> DNO。 而DNO -> SNO却不存在,DNO -> LOCATION, 因此关键辽 SNO 对 LOCATION 函数决定是通过传递依赖 SNO -> LOCATION 实现的。也就是说,SNO不直接决定非主属性LOCATION。
解决目地:每个关系模式中不能留有传递依赖。
解决方法:分为两个关系 S(SNO,SNAME,DNO),D(DNO,DNAME,LOCATION)
注意:关系S中不能没有外关键字DNO。否则两个关系之间失去联系。

BCNF:如果关系模式R(U,F)的所有属性(包括主属性和非主属性)都不传递依赖于R的任何候选关键字,那么称关系R是属于BCNF的。或是关系模式R,如果每个决定因素都包含关键字(而不是被关键字所包含),则RCNF的关系模式。
例:配件管理关系模式 WPE(WNO,PNO,ENO,QNT)分别表仓库号,配件号,职工号,数量。有以下条件
a.一个仓库有多个职工。
b.一个职工仅在一个仓库工作。
c.每个仓库里一种型号的配件由专人负责,但一个人可以管理几种配件。
d.同一种型号的配件可以分放在几个仓库中。
分析:由以上得 PNO 不能确定QNT,由组合属性(WNO,PNO)来决定,存在函数依赖(WNO,PNO) -> ENO。由于每个仓库里的一种配件由专人负责,而一个人可以管理几种配件,所以有组合属性(WNO,PNO)才能确定负责人,有(WNO,PNO)-> ENO。因为 一个职工仅在一个仓库工作,有ENO -> WNO。由于每个仓库里的一种配件由专人负责,而一个职工仅在一个仓库工作,有 (ENO,PNO)-> QNT。
找一下候选关键字,因为(WNO,PNO) -> QNT,(WNO,PNO)-> ENO ,因此 (WNO,PNO)可以决定整个元组,是一个候选关键字。根据ENO->WNO,(ENO,PNO)->QNT,故(ENO,PNO)也能决定整个元组,为另一个候选关键字。属性ENO,WNO,PNO 均为主属性,只有一个非主属性QNT。它对任何一个候选关键字都是完全函数依赖的,并且是直接依赖,所以该关系模式是3NF。
分析一下主属性。因为ENO->WNO,主属性ENO是WNO的决定因素,但是它本身不是关键字,只是组合关键字的一部分。这就造成主属性WNO对另外一个候选关键字(ENO,PNO)的部 分依赖,因为(ENO,PNO)-> ENO但反过来不成立,而P->WNO,故(ENO,PNO)-> WNO 也是传递依赖。
虽然没有非主属性对候选关键辽的传递依赖,但存在主属性对候选关键字的传递依赖,同样也会带来麻烦。如一个新职工分配到仓库工作,但暂时处于实习阶段,没有独立负责对某些配件的管理任务。由于缺少关键字的一部分PNO而无法插入到该关系中去。又如某个人改成不管配件了去负责安全,则在删除配件的同时该职工也会被删除。
解决办法:分成管理EP(ENO,PNO,QNT),关键字是(ENO,PNO)工作EW(ENO,WNO)其关键字是ENO
缺点:分解后函数依赖的保持性较差。如此例中,由于分解,函数依赖(WNO,PNO)-> ENO 丢失了, 因而对原来的语义有所破坏。没有体现出每个仓库里一种部件由专人负责。有可能出现 一部件由两个人或两个以上的人来同时管理。因此,分解之后的关系模式降低了部分完整性约束。

一个关系分解成多个关系,要使得分解有意义,起码的要求是分解后不丢失原来的信息。这些信息不仅包括数据本身,而且包括由函数依赖所表示的数据之间的相互制约。进行分解的目标是达到更高一级的规范化程度,但是分解的同时必须考虑两个问题:无损联接性和保持函数依赖。有时往往不可能做到既有无损联接性,又完全保持函数依赖。需要根据需要进行权衡。

1NF直到BCNF的四种范式之间有如下关系:
BCNF包含了3NF包含2NF包含1NF

小结:
目地:规范化目的是使结构更合理,消除存储异常,使数据冗余尽量小,便于插入、删除和更新
原则:遵从概念单一化 "一事一地"原则,即一个关系模式描述一个实体或实体间的一种联系。规范的实质就是概念的单一化。
方法:将关系模式投影分解成两个或两个以上的关系模式。
要求:分解后的关系模式集合应当与原关系模式"等价",即经过自然联接可以恢复原关系而不丢失信息,并保持属性间合理的联系。

注意:一个关系模式结这分解可以得到不同关系模式集合,也就是说分解方法不是唯一的。最小冗余的要求必须以分解后的数据库能够表达原来数据库所有信息为前提来实现。其根本目标是节省存储空间,避免数据不一致性,提高对关系的操作效率,同时满足应用需求。实际上,并不一定要求全部模式都达到BCNF不可。有时故意保留部分冗余可能更方便数据查询。尤其对于那些更新频度不高,查询频度极高的数据库系统更是如此。

在关系数据库中,除了函数依赖之外还有多值依赖,联接依赖的问题,从而提出了第四范式,第五范式等更高一级的规范化要求。在此,以后再谈。

各位朋友,你看过后有何感想,其实,任何一本数据库基础理论的书都会讲这些东西,考虑到很多网友是半途出家,来做数据库。特找一本书大抄特抄一把,各位有什么问题,也别问我了,自已去找一本关系数据库理论的书去看吧,说不定,对各位大有帮助。说是说以上是基础理论的东西,请大家想想,你在做数据库设计的时候有没有考虑过遵过以上几个范式呢,有没有在数据库设计做得不好之时,想一想,对比以上所讲,到底是违反了第几个范式呢?
我见过的数据库设计,很少有人做到很符合以上几个范式的,一般说来,第一范式大家都可以遵守,完全遵守第二第三范式的人很少了,遵守的人一定就是设计数据库的高手了,BCNF的范式出现机会较少,而且会破坏完整性,你可以在做设计之时不考虑它,当然在ORACLE中可通过触发器解决其缺点。以后我们共同做设计之时,也希望大家遵守以上几个范式。

posted @ 2008-07-02 00:25 张树坤 阅读(27) | 评论 (0)编辑
候选关键字(Candidate Key) 在给定关系中,具有唯一标识特性的一个或多个属性被称为该关系的候选关键字。例如,学生关系中的学号(每个学生只有一个学号)。
posted @ 2008-07-02 00:23 张树坤 阅读(23) | 评论 (0)编辑
4GL

http://wiki.ccw.com.cn/4GL
程序设计语言的划代问题远比计算机的划代复杂,目前所见到的划代观点有4种之多。这儿例举一种观点,他们将编程语言划分如下:1GL是汇编语言;2GL是高级程序设计语言,如FORTRAN,ALGOL,BASIC,LISP等;3GL是增强性的高级程序设计语言,如PASCAL,ALGOL68,FORTRAN77等;4GL是按计算机科学理论指导设计出来的结构化语言,如ADA,MODULA- 2,SMALLTALK-80等。

一般认为4GL具有简单易学,用户界面良好,非过程化程度高,面向问题,只需告知计算机“做什么”,而不必告知计算机“怎么做”,用4GL编程使用的代码量较之COBOL、PL/1明显减少,并可成数量级地提高软件生产率等特点。许多4GL为了提高对问题的表达能力,也为了提高语言的效率,引入了过程化的语言成分,出现了过程化的语句与非过程化的语句交织并存的局面,如LINC、NOMAD、IDEAL、 FOCUS、NATURAL等均是如此。


确定4GL的标准

  确定一个语言是否是一个4GL,主要应从以下标准来进行考察:

  (1)生产率标准:4GL一出现,就是以大幅度提高软件生产率为己任的,4GL应比3GL提高生产率一个数量级以上。

  (2)非过程化标准:4GL基本上应该是面向问题的,即只需告知计算机“做什么”,而不必告知计算机“怎么做”。当然4GL为了适应复杂的应用,而这些应用是无法“非过程化”的,就允许保留过程化的语言成分,但非过程化应是4GL的主要特色。

  (3)用户界面标准:4GL应具有良好的用户界面,应该简单、易学、易掌握,使用方便、灵活。

  (4)功能标准:4GL要具有生命力,不能适用范围太窄,在某一范围内应具有通用性。


4GL的不足

  虽然4GL具有很多优点,也有很大的优势,成为了目前应用开发的主流工具,但也存在着以下严重不足:

  (1)4GL虽然功能强大,但在其整体能力上却与3GL有一定的差距。这一方面是语言抽象级别提高以后不可避免地带来的(正如高级语言不能做某些汇编语言做的事情);另一方面是人为带来的,许多4GL只面向专项应用。有的4GL为了提高对问题的表达能力,提供了同3GL的接口,以弥补其能力上的不足。如 Oracle提供了可将SQL语句嵌入C程序中的工具PRO*C。

  (2)4GL由于其抽象级别较高的原因,不可避免地带来系统开销庞大,运行效率低下(正如高级语言运行效率没有汇编语言高一样),对软硬件资源消耗严重,应用受硬件限制。

  (3)由于缺乏统一的工业标准,4GL产品花样繁多,用户界面差异很大,与具体的机器联系紧密,语言的独立性较差(SQL稍好),影响了应用软件的移植与推广。

  (4)目前4GL主要面向基于数据库应用的领域,不宜于科学计算、高速的实时系统和系统软件开发。第四代语言的分类


  按照4GL的功能可以将它们划分为以下几类:

  1.查询语言和报表生成器

  查询语言是数据库管理系统的主要工具,它提供用户对数据库进行查询的功能。有的查询语言(如SQL)实际上还包括有查询、操纵、定义、控制四种功能。

  报表生成器(Report Generator)是为用户提供的自动产生报表的重要工具,它提供非过程化的描述手段让用户很方便地根据数据库中的信息来生成报表,如ADF 。

  2.图形语言

  图形信息较之一维的字符串、二维的表格信息更为直观、鲜明。我们在软件开发过程中所使用的数据流图、结构图、框图等均是图形。人们自然要设想,是否可以用图形的方式来进行软件开发呢?可见视屏、光笔、鼠标器的广泛使用为此提供了良好的硬件基础,Windows和X-Window为我们提供了良好的软件平台。目前较有代表性的是Gupta公司开发的SQL Windows系统。它以SQL语言为引擎,让用户在屏幕上以图形方式定义用户需求,系统自动生成相应的源程序(还具有面向对象的功能),用户可修改或增加这些源程序,从而完成应用开发。

  3.应用生成器

  应用生成器(Application Generator)是重要的一类综合的4GL工具,它用来生成完整的应用系统。应用生成器让用户不必使用多个软件,而只用这样一个综合工具来实现多种功能。应用生成器按其使用对象可以分为交互式和编程式二类。属于前者的有FOCUS、RAMIS、MAPPER、UFO、NOMAD、SAS等。它们服务于维护、准备和处理报表,允许用户以可见的交互方式在终端上创立文件、报表和进行其它的处理。目前较有代表性的有Power Builder和Oracle的应用开发环境。Oracle提供的SQL*FORMS、SQL*MENU、SQL*REPORTWRITER等工具建立在 SQL语言基础之上,借助了数据库管理系统强大的功能,让用户交互式地定义需求,系统生成相应的屏幕格式、菜单和打印报表。编程式应用生成器是为建造复杂系统的专业程序人员设计的,如NATURAL、FOXPRO、MANTIS、IDEAL、CSP、DMS、INFO、LINC、FORMAL、 APPLICATION FACTORY以及作者设计的OO-HLL等即属于这一类。这一类4GL中有许多是程序生成器(Program Generator),如LINC生成COBOL程序,FORMAL生成PASCAL程序等。为了提供专业人员建造复杂的应用系统,有的语言具有很强的过程化描述能力。虽然语句的形式有差异,其实质与3GL的过程化语句相同,如Informix-4GL和Oracle的PRO*C。

  4.形式规格说明语言

  软件规格说明是对软件应满足的需求、功能、性能及其它重要方面的陈述,是软件开发的基础。按照软件生存周期的阶段来划分,有软件的需求规格说明、功能规格说明、设计规格说明等。用来书写规格说明的语言称为规格说明语言。传统的规格说明语言是自然语言。在我国,主要使用现代汉语来表达软件的规格说明。自然语言为开发者和用户所熟悉,易于使用。但也会不可避免地将自然语言的歧义性、不精确性引入到软件规格说明中,从而给软件的开发和软件的质量带来隐患。形式的规格说明语言则很好地解决了上述问题,而且还是软件自动化的基础。从形式的需求规格说明和功能规格说明出发,可以自动或半自动地转换成某种可执行的语言(如高级语言)。需求规格说明和功能规格说明是面向问题、非过程化的,因此属于4GL。这一类语言有Z、NPL、SPECINT以及作者设计的JAVASPEC。设计规格说明语言由于包含了大量过程化成分,原则上不应划入4GL。

posted @ 2008-06-18 13:42 张树坤 阅读(22) | 评论 (0)编辑
     摘要: 通过解释器模式实现阿拉伯数字与罗马数字的相互转换。具体的模式分析解说日后补发。Delphi代码:unituInt2RomeInterpreter;{单元说明:将整数转换为罗马数字Interpreter解释器模式练习。作者:张树坤时间:2008-06-11}interfacetypeTInt2RomeContext=class;TRomeCharList=array[1..9]ofstring;TI... 阅读全文
posted @ 2008-06-13 17:18 张树坤 阅读(108) | 评论 (0)编辑
模式编程法则
1、开闭法则(OCP)
  开闭法则(Open Closed Principle, OCP):软件实体(模块)应该易于扩展(开放),但免于修改(关闭)。
2、Liskov代换法则(LSP)
  Liskov代换法则(Liskov Substitution Principle, LSP)派生类应该可以用其基类代换。
3、依赖反转法则(DIP)
  依赖反转法则(Dependency Inversion Principle, DIP):依赖抽象而不依赖具体。
4、接口隔离法则(ISP)
  接口隔离法则(Interface Segregation Principle, ISP):不应该强迫客户端依赖于他们用不上的方法。
5、单一职责法则(SRP)
  单一职责法则(Single-Responsibility Principle, SRP):一个类应该仅有一个原因导致其变化。

http://www.zhangsk.cn/

刚刚在网上找到了一个比较不错的解释:
      “开-闭”原则
        一个软件实体应当对扩展开放,对修改关闭。当需求改变时我们可以对模块进行扩展,使其具有新的功能对更改是封闭的,对模块扩展时,不需要改动原来的代码面对抽象而不是面对细节,抽象比细节活的更长僵化的设计——如果程序中一处改动产生连锁反应。

     
       里氏代换原则
       任何积累可以出现的地方,子类一定可以出现。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤是抽象化,而积累与子类的继承关系就是抽象化的具体体现,所以里氏代换原则是对实现抽象化的具体步骤的规范。


        依赖倒转原则
        要依赖于抽象,不要依赖于实现。看上去依赖倒转原则与“开-闭”原则有很大的相似指出,实际上,它们之间的关系是目标和手段之间的关系。“开-闭”原则是目标,而达到这一目标的手段是依赖倒转原则。

        合成/聚合复用原则
        要尽量使用合成/聚合,而不是集成关系达到复用的目的。显然,合成/聚合复用原则使与里氏代换原则相辅相成的,两者又都是对实现“开-闭”原则具体步骤的规范。前者要求设计师首先考虑合成/聚合关系,后者要求在使用集成关系时,必须确定这个关系是符合一定条件的。
     
         迪米特法则
         一个软件实体应当与尽可能少的其他实体发生相互作用。当一个系统面临功能扩展的时候,其中会有一些模块,它们需要修改的压力比其他一些模块要大。最后的结果可能是这些模块需要修改或者不需要修改。但是不论是哪种情况,如果这些模块是相对孤立的,那么它们就不会将修改的压力传递给其他的模块。

        接口隔离原则
        应当为客户端提供尽可能小的单独的接口,而不要提供大的总接口。显然,接口隔离原则与广义的迪米特法则都是对一个软件实体与其他的软件实体的通信限制。广义的迪米特法则要求尽可能的限制通信的宽度和深度。接口隔离原则所限制的是通信的宽度,也就是说,通信应当尽可能地窄。显然,遵守接口隔离原则与迪米特法则,会使一个软件系统在功能扩展地过程种,不会将修改地压力传递到其他的对象。


posted @ 2008-06-13 16:54 张树坤 阅读(95) | 评论 (0)编辑
模式解说:
  责任链模式是一种对象的行为模式,它将处理客户端请求的那些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。其目的是使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
 
UML结构图


//先看一个复杂的if语句,我已经将该语句在面向过程的范围内进行了重构,看起来好一点。
unit uAudit;

interface

type
  TAudit 
= class(TObject)
  
public
    procedure ProcessAudit(money: Integer);
  end;

implementation

{ TAudit }

procedure TAudit.ProcessAudit(money: Integer);  
//处理审批
  procedure ProcessByDirectorate;
  begin
    Writeln(
'500000元以上的审批,董事会处理');
  end;  

  procedure ProcessByPresident;
  begin
    
if money > 500000 then
      ProcessByDirectorate
    
else
      Writeln(
'50001-500000元的审批,总裁处理');
  end;
   
  procedure ProcessByManager;
  begin
    
if money > 50000 then
      ProcessByPresident
    
else
      Writeln(
'5001-50000元的审批,经理处理');
  end;  
begin
  
if money > 5000 then
    ProcessByManager
  
else
    Writeln(
'5000元以下的审批,主任处理');
end;

end.

下面看看职责链的实现,并对该if进行重构
// Added by zhangsk 2008-6-9 23:09:08 使用职责链模式重构
unit uAuditChain;

interface

type
  THandle 
= class(TObject)
  
private
    FSuccessor: THandle;
    procedure SetSuccessor(
const Value: THandle);
  
public
    property Successor: THandle read FSuccessor write SetSuccessor;
    procedure HandleRequest(money: Integer); 
virtualabstract;
  end;

  TDirectorHandle 
= class(THandle) //主任
  public
    procedure HandleRequest(money: Integer); 
override;
  end;

  TManagerHandle 
= class(THandle) //经理
  public
    procedure HandleRequest(money: Integer); 
override;
  end;

  TPresidentHandle 
= class(THandle) //总裁
  public
    procedure HandleRequest(money: Integer); 
override;
  end;

  TDirectorateHandle 
= class(THandle) //董事会
  public
    procedure HandleRequest(money: Integer); 
override;
  end;

implementation

{ THandle }

procedure THandle.SetSuccessor(
const Value: THandle);
begin
  FSuccessor :
= Value;
end;

{ TDirectorHandle }

procedure TDirectorHandle.HandleRequest(money: Integer);
begin
  
if Assigned(FSuccessor) and (money > 5000) then
    FSuccessor.HandleRequest(money)
  
else
    Writeln(
'5000元以下,主任处理');
end;

{ TManagerHandle }

procedure TManagerHandle.HandleRequest(money: Integer);
begin
  
if Assigned(FSuccessor) and (money > 50000) then
    FSuccessor.HandleRequest(money)
  
else
    Writeln(
'5001-50000元,经理处理');
end;

{ TPresidentHandle }

procedure TPresidentHandle.HandleRequest(money: Integer);
begin
  
if Assigned(FSuccessor) and (money > 500000) then
    FSuccessor.HandleRequest(money)
  
else
    Writeln(
'50001-500000元,总裁处理');
end;

{ TDirectorateHandle }

procedure TDirectorateHandle.HandleRequest(money: Integer);
begin
  Writeln(
'500000元以上,董事会处理');
end;

end.

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  uAudit 
in 'uAudit.pas',
  uAuditChain 
in 'uAuditChain.pas';

var
  aAudit: TAudit;

  Director: THandle;
  Manager: THandle;
  President: THandle;
  Directorate: THandle;
begin
  
{ TODO -oUser -cConsole Main : Insert code here }
  
//使用面向过程的方法
  aAudit := TAudit.Create;
  aAudit.ProcessAudit(
500);
  aAudit.ProcessAudit(
6000);
  aAudit.ProcessAudit(
60000);
  aAudit.ProcessAudit(
600000);
  aAudit.Free;

  
//职责链重构后
  Director := TDirectorHandle.Create;
  Manager :
= TManagerHandle.Create;
  President :
= TPresidentHandle.Create;
  Directorate :
= TDirectorateHandle.Create;
  Director.Successor :
= Manager;
  Manager.Successor :
= President;
  President.Successor :
= Directorate;
  Director.HandleRequest(
500);
  Director.HandleRequest(
6000);
  Director.HandleRequest(
60000);
  Director.HandleRequest(
600000);
  Director.Free;
  Manager.Free;
  President.Free;
  Directorate.Free;

  
  Readln;
end.

http://www.zhangsk.cn
posted @ 2008-06-13 16:50 张树坤 阅读(63) | 评论 (0)编辑
一个使用Builder模式进行电脑组装的序列图:


模式解说:
  将一个复杂对象的建造方法从其表现中分离出来,以便同样的建造方法可以建立不同的表现。
 
模式结构:
  TAbstractBuilder:抽象建造者;定义一个抽象接口以创建产品对象的各个部分。
  TConcreteBuilder:具体建造者;实现建造者接口,以创建及装配产品的各个部分。分步骤完成建造工作,在最后提供一个接口来返回该产品的实例。
  TDirector:指导者;使用建造者接口来建造对象。
  TProduct:产品;由建造者负责建造的复杂对象。


UML结构图:

Delphi代码:
unit uBuilder;

interface

type
  IProduct 
= interface(IInterface)
  end;

  TProduct 
= class(TInterfacedObject, IProduct)
  end;

  TAbstractBuilder 
= class(TObject)
  
public
    procedure BuildPart1; 
virtualabstract;
    procedure BuildPart2; 
virtualabstract;
    function GetProduct: IProduct; 
virtualabstract;
  end;

  TConcreteBuilder 
= class(TAbstractBuilder)
  
public
    procedure BuildPart1; 
override;
    procedure BuildPart2; 
override;
    function GetProduct: IProduct; 
override;
  end;

  TDirector 
= class(TObject)
  
private
    FBuilder: TAbstractBuilder;
  
public
    constructor Create(obj: TAbstractBuilder);
    procedure Construct;
  end;

implementation

{ TConcreteBuilder }

procedure TConcreteBuilder.BuildPart1;
begin
  inherited;
  Writeln(
'TConcreteBuilder.BuildPart1');
end;

procedure TConcreteBuilder.BuildPart2;
begin
  inherited;
  Writeln(
'TConcreteBuilder.BuildPart2');
end;

function TConcreteBuilder.GetProduct: IProduct;
begin
  Writeln(
'TConcreteBuilder.GetProduct');
  Result :
= nil;
end;

{ TDirector }

procedure TDirector.Construct;
begin
  FBuilder.BuildPart1;
  FBuilder.BuildPart2;
  FBuilder.GetProduct;
end;

constructor TDirector.Create(obj: TAbstractBuilder);
begin
  FBuilder :
= obj;
end;

end.

unit uClient;

interface

uses
  uBuilder;

type
  TClient 
= class(TObject)
  
public
    procedure Process;
  end;

implementation

{ TClient }

procedure TClient.Process;
var
  Builder1: TAbstractBuilder;
  Director1: TDirector;
begin
  Builder1 :
= TConcreteBuilder.Create;
  Director1 :
= TDirector.Create(Builder1);
  Director1.Construct;
end;

end.

program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  uBuilder 
in 'uBuilder.pas',
  uClient 
in 'uClient.pas';

var
  Client: TClient;
begin
  
{ TODO -oUser -cConsole Main : Insert code here }
  Client :
= TClient.Create;
  Client.Process;
  Client.Free;
  Readln;
end.

posted @ 2008-06-13 16:42 张树坤 阅读(76) | 评论 (0)编辑
模式解说:
  命令模式将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。
  Comnand模式的思想是把命令封装在一个类中,就是这里的ICommand接口,同时把接收对象也封装在一个类中就是这里的TReceiver类中,由调用这个命令的类祈求者TInvoker类来调用。
  Comnand模式和面向过程的回调函数是一样的,注册回调函数和为具体的命令对象设置接受者对象相似,采用Command模式对命令的发出者和命令的执行者进行了解耦。

UML结构图

// Added by zhangsk 2008-6-13 14:47:40 command模式学习
unit uCommand;

interface

uses
  SysUtils;

type
  TReceiver 
= class(TObject) //接受者,相当于实现回调的具体功能;
  public
    procedure Action;
  end;

  ICommand 
= interface //命令接口
  ['{062332DB-F4A4-435B-98E3-3E05E7ADBDEF}']
    procedure SetReceiver(
const Value: TReceiver);
    procedure Execute;  
//执行命令
  end;

  TInvoker 
= class(TObject) //祈求者,客户端直接调用祈求者
  private
    FCommand: ICommand;     
//维护一个具体命令
    procedure SetCommand(const Value: ICommand);
  
public
    property Command: ICommand read FCommand write SetCommand; 
//设置具体命令
    procedure Invoker;      //客户端操作祈求者的具体方法;
  end;

  TConcreteCommand 
= class(TInterfacedObject, ICommand) //具体命令
  private
    FReceiver: TReceiver;
  
public
    procedure SetReceiver(
const Value: TReceiver);
    procedure Execute;      
//具体命令执行的实现
  end;

implementation

{ TInvoker }

procedure TInvoker.Invoker;
begin
  
if Supports(FCommand, ICommand) then
    FCommand.Execute;
end;

procedure TInvoker.SetCommand(
const Value: ICommand);
begin
  FCommand :
= Value;
end;

{ TConcreteCommand }

procedure TConcreteCommand.Execute;
begin
  
if Assigned(FReceiver) then  //相当实现了一个回调;TCommand.Execute回调TReceiver.Action
    FReceiver.Action;
  Writeln(
'Command By TConcreteCommand.Execute');
end;

{ TReceiver }

procedure TReceiver.Action;
begin
  Writeln(
'TReceiver.Action');
end;

procedure TConcreteCommand.SetReceiver(
const Value: TReceiver);
begin
  FReceiver :
= Value;
end;

end.

unit uClient;

interface

uses
  uCommand;

type
  TClient 
= class(TObject)
  
private
    FReceiver: TReceiver;
    FCommand: ICommand;
    FInvoker: TInvoker;
  
public
    constructor Create;
    destructor Destroy; 
override;
    procedure TestCommand;
  end;

implementation

{ TClient }

constructor TClient.Create;
begin
  inherited Create;
  FReceiver :
= TReceiver.Create;
  FCommand :
= TConcreteCommand.Create;
  FInvoker :
= TInvoker.Create;
  FInvoker.Command :
= FCommand;
  FCommand.SetReceiver(FReceiver);
end;

destructor TClient.Destroy;
begin
  
if Assigned(FReceiver) then  //<