J2EE学习总结(转载)

来源:互联网 发布:jpg整合软件 编辑:程序博客网 时间:2024/05/16 17:35

J2EE学习总结(转载)

Java是面向对象的(object-oriented)编程语言,有三个主要机制(mechanism),封装(encapsulation)、继承(inheritance)多态(polymorphism).
封装:利用抽象数据类型将数据和基于数据的操作封装在一起,数据被保护在抽象数据类型的内部,系统的其他部分只有通过包裹在数据外面的被授权的操作,才能够与这个抽象数据类型交流和交互。
关于封装,你可以扮演两种角色:
封装者:封装一个类,供别人使用。
类使用者:使用别人封装好的了类。
继承:继承也是封装的一种。
      目的1:达到代码的可复用性。
      目的2:继承接口,达到接口复用,为多态预做准备。
      继承一定要扩充或修改,否则没有意义。
多态:当某变量的实际类型和形式类型不一致时,调用此变量的method,一定会调用到正确的版本,也就是实际类型的版本。
      问题:
      1.为什么实际类型和形式类型不一致?
        实际类型也称执行期类型(runtime type),
        形式类型也称编译期类型(compile-time type)
      2.多态能够带来什么好处?
      注意:
      1.多态的机制只用在method上,不用在field上。
      2.多态的机制只用在instance method上,不用在class method上。 更明白的说:多态是依赖接口的继承,程序码的继承完全无涉于多态。  

 


                           EJB体系介绍
---什么是EJB
   EJB的结构是开发和部署于组件的分布式商务应用程序的一种组件结构。利用EJB结构开发的应用程序是可伸缩的、事物性的、多用户安全的。这些应用程序可能只需编写一次,然后可以部署在任何支持EJB规范的服务器平台上。
要点:
1.EJB是一种组件规范
    一个组件是一段实现一系列确定接口的程序代码。这些组件是可维护的,各自具有自己的逻辑。组件不是一个完整的应用程序,它们不能独自运行。它们是程序的组成模块,主要用于解决大型问题。
    EJB是Java技术中部署在服务器端的一种组件结构标准,它是一个协议。它为基于组件的服务器端应用程序提供了一种与厂商无关的Java接口,可以让任何符合EJB规范的组件运行于每一种符合EJB规范的服务器上。
2.EJB是基于分布式对象结构的
    所谓分布式对象结构,简单的说就是系统的不同部分被部署到不同的计算机上,这些计算机可能相隔很远;也就是说,分布式对象结构允许远程获得商务逻辑和数据。所有的分布式对象协议都建立在相同的基础结构之上,这样的结构也使得在一台计算机的一个对象看上去好像分布在不同的计算机上。
EJB的分布式对象结构使用的是代理对象。客户端并不直接访问Enterprise bean的实例,而是使用Enterprise bean的远程接口来访问Enterprise bean的实例。所以除了对Enterprise bean类本身进行编码外,EJB开发人员还必须为Enterprise bean定义一个本地接口和一个远程接口。这些接口类的实现通常由容器生成,因此部署EJB组件是开发人员和EJB容器的合作行为,这些接口类所实现的分布式对象称为EJB对象。 
3.EJB组件位于中间层
   对于基于WEB应用程序的开发,可扩展性是相当重要的,而传统的两层(c/s)应用程序不便于升级扩展,因此更加适合用于Internet的三层及多层结构便应运而生了。在三层结构中,表示逻辑层在客户端(第一层),商务逻辑在中间层(第二层),其它资源,如数据库,位于后端(第三层)。
EJB位于商务逻辑层,遵循EJB规范,应用程序开发者不用担心周围框架的实现和接口的连接问题,只需专心致志地实现所需的商务逻辑即可;在系统需要升级或扩展时,只需改动需要变动的局部代码,不会出现“牵一发而动全身”的局面。EJB服务器提供了分布式对象系统所需的所有任务,例如组件的生命周期的管理、负载平衡、资源池管理、安全性、实现高速缓存等等。这大大减轻了开发者的负担,也是EJB得以迅速流行的重要原因。
二EJB体系中各角色的分析
   在《EJB规范》中定义了六种不同的角色,并提倡构建EJB时分解成不同的部分进行。每一个角色可以由不同的团体来担任,而且每个角色所作的工作都必须遵循EJB规范,以保证彼此之间的兼容性。因为每个部分都是各自分别进行的,构建一个企业级部署所需的时间就会显著的减少。而且由于每个团体的分工明确,长期积累的经验可以使得系统的每个部分都达到较高的质量。
1.        EJB组件供应商(Enterprise Bean Provider)
EJB的供应商是某个应用领域的专家级企业,他们提供可复用的商业组件和EJB。EJB不是一个完整解决方案中的一个组件。EJB组件供应商不是精通系统级的编程专家,因此,他们通常不在EJB中提供系统级服务,如事务、同步、安全、分布式计算等,这些服务往往要由EJB服务器来完成。
EJB供应商以ejb-jar文件包的形式提供EJB组件,其中含有Enterprise Beans,每个EJB都要定义的remote和home接口,编写执行商业逻辑的EJB class,提供部署EJB的部署文件和环境属性。
2.        应用程序集成者(Application Assembler)
应用程序集成者负责整个应用程序的架构。他们有责任理解如何使用使各种各样的组件配合在一起,并编写应用程序整合这些组件。一个应用程序集成者可以依照这样的方法创建一些这样的组件。他们的工作是建造一个可以用大量可部署的组件构成的应用程序。应用程序集成者输出的可能是一个新的Enterprise Beans,或是非Enterprise Beans 的程序(如servlets、applets或scripts),集成者也可替应用程序写一个GUI.
应用程序集成者可以实现一些或所有这些任务:
1.        基于某个商业问题的知识,决定应该使用一个业已存在的组件,还是创建一个新的EJB;从大体上,设计应用程序的组成。
2.        提供用户接口(可能是Swing、servlet/Jsp、application/applet、或一个web service)。
3.        编写一个新的EJB来解决某个特定的商业问题。
4.        在一个组件中编写调用由Bean提供商提供现成的Bean.
5.        编写整合的代码来映射数据,使组件间可以相互通信。毕竟,组件自己不能神奇地组合在一起解决一个商业问题,特别是不同厂商之间的组件。
3. EJB部署者
   应用程序集成者做好一个应用后,必须部署在某个运行环境中。这时会以下一些难题:
1.        用一个防火墙或其他保护措施来保障安全。
2.        整合一个LDAP服务器实现安全的目录服务,如Lotus Notes或Microsoft Active Directory.
3.        选择提供所需性能级别的硬件。
4.        提供额外的硬件或其它资源来实现可靠性与容错性。
5.        调整系统性能。
EJB部署者熟悉特定的操作环境并掌握上面所列的技能。他们理解如何在服务器端部署Beans和如何为一个特定的系统定制Beans。EJB部署者可以改变Beans,也可以改变服务器,并决定在一个环境里哪些Bean应该被部署。
4.EJB容器供应商(EJB Container Provider)
   容器供应商提供EJB容器(应用程序服务器),这是Enterprise Beans 的运行环境。这个容器支持Enterprise Beans的中间件服务并管理他们。
   常见的容器:BEA: WebLogic      iPlanet: iPlanet Application server
IBM: WebSphere      Oracle: Oracle 9i
Macromedia: Jrun     Persistence: PowerTier
   Brokat: Gemstone/J    HP:Bluestone
IONA: iPortal         Borland: AppServer
开源: Jboss
另:bean---容器约定
在EJB服务器上包含bean的环境经常被认为是容器。容器更多的是一个概念,而不是一个模型。在概念上,容器作为bean类和EJB服务器的媒介物。容器管理EJB对象和一个特定类型bean的EJB home,并帮助这些模型管理bean资源和给运行时bean实例提供诸如事务、安全、并发性、命名等基本服务。从概念上来说,一个EJB服务器可以有很多容器,每个容器可以包含一种或多种类型的Enterprise bean.
5.系统管理员(System Administrator)
一旦部署成功,系统管理员就要介入并检查系统的稳定性。利用EJB服务商提供的实事监控和管理工具。例如:Tivoli和Computer Associates公司的产品。
6.开发工具供应商(Tool Provider)
为了简化组件开发过程,应该有一些标准化方法来创建、管理、维护组件。在EJB开发过程中,有多种集成开发环境(IDE)可以帮助你快速地创建和调试组件。
例如:Webgain:   Visual Café
       IBM:       VisualAge for java
       Borland    Jbuilder
有一些工具帮助你用UML语言来创建组件模型
例如:Togethersoft:  Together/J
      Rational:      Rational Rose
组件组织工具: Flashline,ComponentSource
测试工具:     JUnit, RSW Software
创建工具:     Ant
EJB component开发简介
1.EJB component的分类:
1.        session bean
2.        entity bean
3.        message-drived bean
2.EJB Component 的组成部分:
#1.Enterprise Bean 类:
包含了组件的实现细节,是实际完成bean功能的地方。EJB容器根据需要调用这个类对bean进行实例化。EJB规范定义了很多标准接口,可供编写、实现bean的类继承,这些接口定义了一些bean类必须实现的接口,以便用户的bean类对外暴露所有的bean都必须提供的特定方法,因为EJB容器需要利用这些方法来对bean进行管理。这些接口集中在javax.ejb.EnterpriseBean接口中,它扩展了java.io.Serializable接口。这个接口是标记接口,实现它表明所编写的是一个真正的Enterprise Bean类。由于它没有扩展Remote接口,所以bean本身是不具备网络功能的,无法通过网络让客户端直接调用,相应的网络和中间件功能是通过下面的EJB对象提供的。不同类型的Enterprise Bean实现不同的接口,在这些接口中分别定义了一些必须的方法,这些方法都是管理bean的方法,是供容器调用的,bean的客户端永远也不会调用。在此基础上再添加用户所需的业务方法等。
#2.EJB对象:
     在服务器端,一个EJB对象是一个实现了bean的远程接口(具有网络功能)的分布式对象,它在服务器端上包装了bean的实例。EJB对象是容器供应商工具产生的,由EJB容器自动生成,事物处理、安全管理、持久性控制等中间件服务是由容器提供的,EJB对象由容器控制在适当的时机调用所需的服务,这些服务对客户而言是透明的。这种委托机制是EJB体系最大的优点之一。通过委托,用户在实现bean时可以只关注于自己要完成的业务逻辑。由EJB对象透明的完成其他复杂的功能。对客户端而言,所见到的只是EJB对象,只能调用它的方法,因而在EJB对象中,必须复制bean类的所有业务方法并暴露给客户端。注意,EJB对象的具体实现随容器的不同而不同,但客户端是感觉不到的。
#3.Remote接口
     遵照EJB规范,所有的Remote接口都必须来源于一个通用的接口,即javax.ejb.EJBObject接口,该接口扩展了java.rmi.Remote,包含了EJB对象必须实现的方法。除与应用程序本身有关的违例,远程接口中的每个方法都必须在自己的throws从句中声明java.rmi.RemoteException.这些方法是容器生成EJB对象时实现的。Remote接口中还必须复制bean中的业务方法。(RMI)接口的属性必须是public.作为参数或返回值传递的一个远程对象(不管是直接,还是本地对象中嵌入)必须声明为远程接口,不可声明为实施类。
#4.Home对象
     客户端调用的是EJB对象的方法,而不是直接调用bean的方法。但客户端如何获得EJB对象的引用的呢?由于EJB对象可能分布在网络上,客户端无法直接生成EJB对象的实例。同时,EJB倡导位置透明性,客户端是不知道EJB对象的具体位置的。为了获得EJB对象的引用,客户端代码从home对象处要求得到一个EJB对象,home对象也是容器自动生成的,它是EJB对象的“制造工厂”它能够完成以下功能:生成、查找(仅限于实体bean)、删除。
#5.Home接口
     它继承了javax.ejv.EJBHome 接口,而它扩展了java.rmi.romote接口。开发者必须定义home接口,容器厂商则提供从home接口中产生home对象实现的方法。
#6.Local接口和EJBLocal对象
    它们分别是remote接口和EJB对象的另一种更高性能的实现。在原来的规范中,remote接口是将bean的方法暴露在网络上,对这些方法的调用都是通过RMI实现的,而不管所调的bean处于什么位置。在某些情况下,比如客户端所调用的bean与自身在同一个java虚拟机上,由于不得不按照RMI的方法完成,付出了不必要的网络开销,导致性能下降。为了解决这个问题,引入了Local接口,它不扩展Remote接口,是标准的java接口,包含了与Remote接口相似的方法。
#7.LocalHome接口和LocalHome对象
#8.XMl文件
     描述了我们的bean对中间件服务方面的要求。
3.EJB Component的调用流程
EJB Component在部署到应用服务器上之后,客户端就可以调用它来完成各种功能。过程如下:
1.        客户端首先通过JNDI服务检索Home对象。在EJB应用部署到应用服务器上之后,容器会自动获得Home对象的信息并将其加入到JNDI中。
2.        JNDI服务返回所查找的Home对象的引用。
3.        Home对象的创建或者查找EJB对象。
4.        Home对象将获得的EJB对象返回给客户端。
5.        客户端利用获得的EJB对象引用,调用业务方法。
6.        EJB对象获得对应bean的一个实例并将相应的业务方法调用传递给该实例。
7.        Bean实例通过其实现代码,完成相应的业务逻辑并将结果返回给EJB对象。
8.        EJB对象将方法的结果返回给客户端。
4.EJB Component开发实例
1.        编写组成EJB Component的各个.java文件,包括接口文件、EJB类文件以及helper等其他需要的文件并编译成.class文件。
2.        编写EJB Component的部署描述。
3.        用jar工具形成EJB-jar文件,其中包含.class文件和部署描述符。
4.        在实际的EJB Server上部署bean,配置相应的参数以及bean需要的资源,这个过程随EJB Server的不同而有所不同。
5.        编写客户端代码对bean的功能进行测试,这一步是可选的。

J2EE
-- j2EE的安装和设置
可以从以下网址下载一个J2EE(j2sdkee-1_3-beta2-win.exe):
http://java.sun.com/j2ee/j2sdkee-beta/index.html
再设置环境变量,假设你的J2EE安装在:C:/j2sdkee1.3 目录下。
J2EE_HOME - 你的J2EE SDK所安装的目录。如本例中的:C:/j2sdkee1.3。
JAVA_HOME - 你的Java 2 SDK 所安装的目录
PATH - 设置为你安装J2EE SDK目录下的bin目录,如本例的C:/j2sdkee1.3/bin
ClassPath -如本例的C:/j2sdkee1.3/lib/j2ee.jar
二 j2EE入门
编写和运行HelloWorld程序,J2EE应用程序一般使用RMI(远程方法调用)来完成客户端与服务器的交互。当然,其间也少不了EJB的作用。本例为一个J2EE应用程序:客户端向服务器发送一个问候语:“Hello,Remote Object”。服务器收到该问候语后打印该问候语,并返回一个字符串作为应答。客户端收到此应答后打印它。
RemoteInterface.java
/**
* 第一步:
* 定义一个新的接口继承javax.ejb.EJBObject。新定义的接口中的每一个方法都必须抛出java.rmi.RemoteException异常。
*/
public interface RemoteInterface extends javax.ejb.EJBObject
{
public String message(String str)throws java.rmi.RemoteException;
}

RemoteObject.java

/**
* 第二步:
* 定义一个类来实现javax.ejb.SessionBean接口。并在该类中实现在第一步中编写的接口中所定义的方法。
*/
public class RemoteObject implements javax.ejb.SessionBean
{
public String message(String str)throws java.rmi.RemoteException
{
System.out.println("Remote Object Received From Client: /""+str+"/""); //打印(从客户端)接收到的字符串。
return "Hello,I'm Remote Object,I received your message: /'"+str+"/'"; //返回一个应答字符串。
}

public RemoteObject() {}
public void ejbCreate() {}
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(javax.ejb.SessionContext sc) {}
}

RemoteHome.java

/**
* 第三步:
* 定义一个类继承javax.ejb.EJBHome 。
*/
public interface RemoteHome extends javax.ejb.EJBHome
{
RemoteInterface create()throws java.rmi.RemoteException,javax.ejb.CreateException;
}

Client.java

/**
* 第四步:
* 定义客户端类。
*/
public class Client
{
public static void main(String[] args)
{
try
{
javax.naming.Context initContext=new javax.naming.InitialContext();
Object obj=initContext.lookup("HelloWorld"); //远程查找,由名字得到对应的对象。
RemoteHome home=(RemoteHome)javax.rmi.PortableRemoteObject.narrow(obj,RemoteHome.class);
RemoteInterface remote=home.create();
String receiveFromRemote=remote.message("Hello,Remote Object!"); //远程方法调用
System.out.println("Client Received From Remote Object: /""+receiveFromRemote+"/"");
}
catch(Exception e)
{
e.printStackTrace();
}
}
}

假设以上四个Java文件存于C:/HelloWorld/下,编译它们如:C:/HelloWorld>javac *.java 。
部署应用程序:
启动Application Deployment Tool:新开一个Dos窗口,键入以下命令,%J2EE_HOME%/bin/deploytool 。该工具启动速度可能比较慢,要耐心等待。启动成功后会出现主界面(此时不要关闭Dos窗口)。在该界面中选 择 File菜 单 ,再选New Application项。Application File Name 输 入 :C:/HelloWorld/HelloWorld.ear 。在 Application Display Name 输 入 你所喜欢的显示名如:HelloWorld。点击 OK,在主界面的树形结构Files-->Applications下将增加新的一项:HelloWorld。这意味着产生了一个新的应用程序。接下来我们要做的就是部署该应用程序。在主界面的树形结构下选中HelloWorld,然后再在主界面的File菜单中选取New-->Enterprise Bean,在弹出的名为“New Enterprise Bean - Introduction”窗口中选取Next跳过第一步,在接下来的一步中,Create New EJB File in Application项中选HelloWorld,在EJB Display Name中填上你喜欢的名字如:Hello World EJB,选择Edit按钮,在弹出的窗口中,Start Directory中填:C:/HelloWorld/,在Available Files中展开树形结构C:/HelloWorld/,选取RemoteInterface.class、RemoteObject.class、RemoteHome.class、Client.class四项,点Add按钮添加,然后按OK确定。此时在Contents框中增加了该四个class。点Next进入下一步。Session项选择Stateless,意为不保存session状态。Enterprise Bean Class选RemoteObject。Enterprise Bean Name中填上你喜欢的名字如:Hello World Bean。Remote Home Interface中选RemoteHome,Remote Interface中选RemoteInterface。选Next进入下一步。接下来的步骤可直接点Finish。这时主界面的树形结构中Files-->Application-->Hello World中将出现Hello World EJB-->Hello World Bean子项。在主界面的树形结构下选中Hello World,然后再在主界面的Tools菜单中选取Deploy,将弹出新的窗口名为“Deploy Hello World - Introduction”。Object to deploy中选Hello World,Target server中选localhost,选中Return Client Jar,在Client Jar File Name中填上:C:/HelloWorld/HelloWorldClient.jar。选Next进入下一步,在Application框的JNDI Name框中双击并填上HelloWorld,注意必须与Client.java中Object obj=initContext.lookup("HelloWorld")的“HelloWorld”保持一致。点Next进入下一步。点Finish完成。这时将出现Deployment Progress窗口。如果有误,该窗口将出现异常信息。如果一切正常,点OK便完成了部署工作。
运行应用程序
新开一个Dos窗口。进入C:/HelloWorld/Classes目录下运行:C:/ HelloWorld/Classes>java-classpath %J2EE_HOME%/lib/j2ee.jar;.;HelloWorldClient.jar; Client 。运行成功则出现如下信息:Client Received From Remote Object: "Hello,I'm Remote Object,I received your message: 'Hello,Remote Object!'" 。而服务端Dos窗口(j2ee -verbose)中出现如下信息:Remote Object Received From Client: "Hello,Remote Object!" 。


错误模式

1、拥护静态类型的理由
静态类型检查:
●通过早期错误检测,提高健壮性。
●通过在最佳的时候作所需的检查,提高性能。
●弥补单元测试的缺点。

成功模式作家的七个习惯

习惯一:让时间来反映(reflect)

在模式写作中的最重要的活动就是反映(reflection)。Bruce Anderson ,最早对我们的工作有影响的人,曾经很多年强调这一点圣谕(mantra)。让时间来阶段性的反映你所做的东东。想想你所做的系统,你所遇到的问题,和你是怎么解决(或没解决)它们的。                                                     
这些阻碍是在日益变短的开发时代中的所有而且是不可想象的。不过反映是紧迫的。有比无头脑的去hack更好的进入创造性轨道的方法.你可能产出大量的工作代码,不过代码量是一个不好的工作量的衡量手段。好的设计的标志实际上恰恰相反---它是量小并且优美。用少量代码完成大量工作。它实现所有的东东"once and only once",就像Kent Beck喜欢说的。它也很灵活,大体积的代码通常不是这样的。
现在,希望人们每年拿出一个月去构想是不实际的。不过你能做的是增量的记录你的经验.当你有重要的问题需要解决时,尝试着马上把它写下来。迅速写下描述问题和为什么它困难的笔记。然后,开始对它的工作。任何时候你尝试一个新方法时,迅速写下它。如果这个方法失败了,也迅速写下它,并且写上为什么它失败了。如果它成功了,也照做。几乎所有人都能用5%的时间写下他们的经验---这也可以作为纪律。                                                       
如果你仔细做了这些,你将会惊讶你所积累的写下来的经验。这是模式的最原始的素材。当然仍然会有很多需要做的,不过你得到了所有重要的可以提炼金子的智慧的矿石。另一个重要的活动是尽你所能多看别人所设计的其它的系统。最好的从其它系统学习的方法是去实际构建它们。如果你们没有时间或金钱去那样做,至少读一下它们。寻找对它们所代表的的问题和怎么表示的理解。
    学习细则(specifications)和文档。读研究系统的论文。浏览OOPSLA和ECOOP进程(proceedings)。软件实践和经验是另一个好的设计和实现的信息来源。
当你测试一个系统,尽你所能努力搜寻所有的东东。试着找出你已经知道的模式。评估解决方案怎么从出版了的那些模式中变化。注意新的设计方案,它们可能代表新的模式。不过记住相关的很少的设计方案是真正的新的。更通常,人们使用已知方案的变体。一个新的和独一无二的解决方案可能不够广泛可用而成为模式的形式。
如果你发现看上去新的东东,在你试着把它写成模式之前确定它在其它的上下文(context)中也可以用。我们开发<<设计模式>>时有一个重要的规则:我们在为一个问题写模式之前,必须找它的两个存在的例子和它的解决方案。这是我们所遵守的特别重要的规则,因为我们在探索不熟悉的领域,并且我们想要确定我们所写的现实中也存在。我们不希望做一个没有任何人有的问题的解决方案。终极的,我们抛弃了许多有吸引力的并且潜在有用的不过没有在实际应用中看到的模式。

习惯二:坚持(adhering to)一个结构

一旦你有了原始素材,你怎么把它们写成模式的形式(form)呢?好,首先,不要假设只有一种模式的形式。没有一种形式适合于所有人。一些人喜欢像Alexander那样更通用的风格。另一些喜欢像<<设计模式>>中使用的更细粒度(fine-grained)方法。还有一些使用完全不同的结构。这些结构所共享的特性只是它们的结构。
如果有一个大多数人同意的著名的术语,它将是亚历山大定义(Alexandrian
canon):一个模式是“对特定问题在特定环境的特定解决方案”(a solution to a problem in a context)。现在我很大胆的稍微修改一下这个定义:一个模式是对特定问题在特定环境的特定解决方案的结构化的清楚的明细的解释(structured exposition)。模式有可识别(recognizable)的部分,这些部分引导它们的应用和比较。这些部分包括一个名字,一个问题的陈述,环境和解决方案的修正,和解决方案本身。这基本上是Alexander模式的结构。我们的模式更进一步把这些基本要素分解成更集中的处理,如“适用性”,“参与者”,和“效果”小节。1994年的模式语言编程(PLoP)进程会议包括令人惊讶的对这些主题的不同的变化。
因此,把模式写在纸上的第一步是决定它的结构。你的模式的平均的信息量越多,你的结构就越重要。一致的结构使模式具有统一性(uniformity),使人们更容易比较它们。结构也帮助人们搜索信息。更少的结构意味着更通用(prose),可能会更适合于休闲的阅读,不过可能不为比较和参考目的所接受。一旦你确定一个结构,确定你将始终如一的遵守它。你不必害怕改变结构,不过你必须在每个模式中改变它,而且当你的模式成熟后这将变得更加代价高昂。
   
习惯三:开始时做得更具体(Being Concrete Early)

在我们的模式中,“意图”部分表现得更直接明了(up-front)。这是因为人们对先提出具体的术语,然后才是抽象术语理解得更好一些。“意图”部分的具体例子给读者一个问题的参考和解决方案的框架。这个部分演示的另一个方面是为什么其它对
这个问题的解决方法失败了,同样用具体的术语。把“意图”部分作为一个介绍,读者能更好的理解(appreciate)通用的解决方案。
具体化的直接结果是需要从真实世界中来的大量例子。例子不应该是“意图”部分所独有的财产。在整个模式中使用例子和反例(counterexample)描绘了关键点。即使是我们模板中最抽象的部分(如“适用性”,“结构”,“参与者”,和“协作”)有时也有例子。举个例子,有些“协作”部分包括表示对象在运行时怎样通信的交互图(interaction diagrams).在讨论模式的抽象部分参考这些例子---即是在你抽象时也要具体点。
另一个直接结果可能是术语:“告诉别人整个真实情况”(telling the whole truth)。这意味着你必须提醒你的读者这个模式的潜在的缺点(pitfalls)。很容易对优点部分喋喋不休;不容易理解它们的缺点并且真诚的谈论这些缺点。没有一个模式是完全没有缺点的,或额外的开销,或在特定环境下的不良表现的,等等。确保你的
读者懂得这个模式会有缺点(fall short)。
   
习惯四:保持模式独一无二和优点突出
(Keeping Patterns Distinct and Complementary)

当你开发多个模式时有一个趋向需要避免。当你写一个模式时,可能趋向于在细节和口径(scope)同时增长。在这时很容易忘记其它模式。模式之间的区别结果变得模糊了,使别人无法分组(collectively)理解模式.它们开始在口径和目的上互相重叠.这可能对作者来说非常清楚,而对新手来说不那么清楚。他们将不知道什么时候去使用一个模式而不是另一个,因为它们之间的区别不那么明显。
所以确保你的模式是正交的(orthogonal)并且它们合力(synergistically)工作。持续问你自己:“模式X和模式Y的区别是什么?”如果解决相同的或相似的问题,你可以把它们合并。如果两个模式使用相似的类层次(hierarchies),则不用担心。在OO编程中有这么多方法使用相对少的继承机制。通常相同的类使用将会导致表示广泛变化的明显的不同对象结构.让模式的意图作为它们不同点,而不是实现它们的类结构的指南。
一个测试你的模式怎样正交和合作的好的方法是保持分离的文档来比较(compare)和对比(contrast)你的模式。在<<设计模式>>中我们提供了多个为了这个目的的部分。试图在写下来的形式下解释模式关系的简单行为给我们对我们的模式的新的视角。不止一次它让我们重新思考它们的一些部分。我的唯一遗憾是我们在游戏中没有早一点重视关系。我建议你尽早开始写下这个附件材料。这可能看上去是做傻事,特别当你有很多模式需要比较。不过当你只有两个模式时,重叠得可能性出现了。初期花时间比较和对比泥的模式将帮助你保持你的模式独一无二而且优点突出。

习惯五:有效的表达。(Presenting Effectively)

你的模式的质量取决于你表达它们好不好。你可能发现世界上最好的模式,但它将不会帮助任何人除非你有效的表达它们。用”表达“(presenting)这个词我表示两件事:打印设置(typesetting)和写作风格。好的打印设置是页面设置(page layout),预览打印(typography),图像(graphics)的技巧的事,而不管打印机质量。使用你能得到的最好的软件工具(文字处理,画图编辑器,等等)。用正规的(liberal)画图使用表达
你的关键点。你可能不会想到需要任何画图,但只要有机会就那么做。至少它们去处枯燥,最好的情况下它们能使你得到无论多少文字解释都无法得到的表现效果。不必所有的画图都要有正式的类图和对象图。非正式的画图,甚至草图常常能表达相同和甚至更多的信息。如果你被“艺术性的被挑战”(artistically challenged)了,那么让
别人为你画这个图。
好的写作风格比好的打印设置更重要。清楚的和真实的(unpretentiously)写作。喜欢脚踏实地的(down-to-earth)风格,而不是陈旧(stuffy)和学术(academic)的风格。人们理解和喜欢(appreciate)一个对话性的腔调,这个腔调让它们对材料更容易被接受(receptive)。在大多数作品中清楚明了和易于阅读是很重要的,不过它们在模式写作中特别的重要。模式概念太新并且主题问题太复杂,以至于有些人很难弄懂它的所有要点。所有让模式友好(approachable)的工作都应该做。
最好的学习怎么用对话式的方式写作的方法是试着去做。确保你所写的所有东东是你能听到你自己对朋友所说的。避免用被动的腔调(passive voice)。打破长句子
和段落。使用日常用语,不要害怕使用缩略语(contractions)。综上所述,让它
听上去自然些。
另一件每个人在生活的同一点要做的是读 一本或两本关于“写作风格”的书。有很多
可供选择的。我最喜欢的3本是Strunk和White的<organization,remarkbly,is not unlike a series of patterns)>>,Joseph M
Williams的<and grace>>和John R. Trimble的<with style:Conversations on the Art of Writing>>。像这些一样的书有为了好的,清楚
的写作的技巧。它们能帮助你不管模式的技术内容而改进你的模式。

习惯六:无拘束的迭代(Iterating Tirelessly)

你不能在第一次就得到一个模式。你甚至不可能在最初10次就得到正确的模式。实际上,你可能永远不会得到完全正确的模式。模式写作是一个永远不会停止(on-going)的过程。这个领域是新的事实不会使事情好转。不过即使它不是..... 甚至有很多模式的好的例子和书帮助你写它们,模式开发(像任何其他种类的开发)将是一个迭代的过程。
期望写和重写你的模式很多次。不要指望一个模式的完美,当你开始写下一个。记住,模式不是单独存在的;它们互相影响。一个模式的一个重要的改变将会很明显的影响其它的模式。用任何迭代,你的努力应该殊途同归(converge)于同一点,不过
那正是模式稳定到让其他人阅读,理解和注释的那一点。

习惯七:收集和采纳反馈(Collecting and Incorporating Feedback)

Cervantes是对的:“对布丁的验证就是在吃它的过程中”(The Proof of Pudding is in the eating)。对一个模式的测试来自于对它的实际应用。实际上,没有一个模式能被信任,直到除了它的作者外的其他人使用了它。模式有潜藏危机的特性(insidious property):它们通常被熟悉牵扯到的问题和它的解决方案的人所完美的 理解。这些人以前不小心用到过这个模式。因此,当他们看见这个模式时,他们能马上懂得它,甚至如果模式并没有被很好的表达。真正的挑战是让那些从来没有遇到这个问题的人也能理解这个模式。没有不去从这些人得到和采纳反馈而让他们懂得的方法。
鼓励你的同事用你的模式术语讨论设计。(让作者也参与这样的讨论也可以。)在你的日常工作中寻找使用你的模式的机会。试着尽你可能的广泛的传播你的模式。你甚至可以把它们提交到会议如PLoP或出版物如C++ Report,Smalltalk Report和Journal of Object-Oriented Programming。这些传播将会最大化你的模式的使用。
一旦反馈开始回来,准备听到最坏的消息。我不记得多少次我被我所认为完全完美的的东东彻底激怒了别人的事实所惊呆了的。否定的反馈会让人失去信心,特别是在最开始你最易受伤害和最想得到反馈时。虽然,有些批评可能不正确或可能只是源于一个简单的误解,大多数的反馈可能是正确地。给你的审阅者怀疑的好处。做得很有帮助性让他们快乐。你可能在长期中让许多,许多人快乐。

原创粉丝点击