JavaScript must be enabled in order for you to view this page. However, it seems JavaScript is either disabled or not supported by your browser. To view this page, enable JavaScript by changing your browser options, then Try again! .

 
我的论坛
Google 网上论坛 Beta 版
Do Best Developer
访问此论坛

java.net.URL的背后

java.net.URL中连续使用了两次工厂方法模式。

关于模式的相关问题可以参阅这里[ http://www.solol.org/technologic/ood/ ]。这里的内容还只是在有限的范围内发布,没有放到公共域中,因为绝大多数内容还没有完成。如果您对这里的内容感兴趣可以和我们联系!

不过这次我们不想讨论关于模式的问题,而是要看一看如下的两个问题:

  • 如何为java.net.URL添加新协议?
  • 如何替换java.net.URL中现有的协议?

在Java SE中,java.net.URL支持很多种协议,具体的情况您需要查阅Javadoc文档。

除了这些内置的协议之外我们也可以实现自己的协议,并将它添加到java.net.URL中。

我们也可以为这些内置的协议中的一种或几种提供我们自己的实现,然后替换Java SE中的实现。

下面的文档照抄自java.net.URL的Javadoc:

If this is the first URL object being created with the specified protocol, a stream protocol handler object, an instance of class URLStreamHandler, is created for that protocol:

  1. If the application has previously set up an instance of URLStreamHandlerFactory as the stream handler factory, then the createURLStreamHandler method of that instance is called with the protocol string as an argument to create the stream protocol handler.
  2. If no URLStreamHandlerFactory has yet been set up, or if the factory's createURLStreamHandler method returns null, then the constructor finds the value of the system property:
    	 java.protocol.handler.pkgs
    
    If the value of that system property is not null, it is interpreted as a list of packages separated by a vertical slash character '|'. The constructor tries to load the class named:
    	<package>.<protocol>.Handler
    
    where <package> is replaced by the name of the package and <protocol> is replaced by the name of the protocol. If this class does not exist, or if the class exists but it is not a subclass of URLStreamHandler, then the next package in the list is tried.
  3. If the previous step fails to find a protocol handler, then the constructor tries to load from a system default package.
    	<system default package>.<protocol>.Handler
    
    If this class does not exist, or if the class exists but it is not a subclass of URLStreamHandler, then a MalformedURLException is thrown.

从文档中不难看出要完成开始时提出的两个问题有两种方式,一种为使用URLStreamHandlerFactory,另一种为使用java.protocol.handler.pkgs属性。

在使用URLStreamHandlerFactory时要注意,每一个JavaVM实例中java.net.URL.setURLStreamHandlerFactory(URLStreamHandlerFactory fac)方法至多调用一次。

视觉语言(A Visual Language)

In the development of the Eclipse style icons, a visual language was formed to describe a variety of concepts in the user interface.

摘自:Eclipse User Interface Guidelines Version 2.1

我们觉得任何一个软件视觉设计者都应该阅读一下这篇指南。您也许还需要阅读一下这个Java Look and Feel Design Guidelines

软件视觉设计是一门非常有内涵的学问,任何人都不应该轻视它。

我们觉得软件视觉设计不仅要在观感上吸引用户还要在概念上提示用户。一个设计良好的软件会反映出特定领域的一系列概念。怎么将这些概念图标化呢?如果我们做的足够好,就可以在该领域形成一种视觉语言。用户可以依据这种视觉语言来使用我们的软件。

Eclipse Style Icons就形成了这样一种视觉语言。

视觉语言来源于对相关领域的理解。

Commons logging中的设计模式

在上一篇中我们说明了Commons logging的关键点:

  • 提供一个日志记录功能的抽象
  • 提供一种从该抽象到具体日志记录实现的映射
  • 提供默认的映射和发现机制,提高自身的易用性

Commons logging使用了三个模式来实现上面的关键点:简单工厂模式、工厂方法模式和适配器模式。

我们本来想为每个模式分别给出结构图,那样比较简单,可是那样不能反映common logging的整体结构。因此我们觉得还是给出总体结构比较好。

仔细的看下面的图,看看您能不能把它们找出来,不要急于往下看。

Commons logging中的设计模式

LogFactory和LogFactoryImpl构成了简单工厂模式。

LogFactory、Log、LogFactoryImpl和Log4JLogger构成了工厂方法模式。

Log、Log4JLogger和org.apache.log4j.Logger构成了适配器模式。

这里我们描述的比较粗糙。关于模式的相关问题可以参阅这里[ http://www.solol.org/technologic/ood/ ]。这里的内容还只是在有限的范围内发布,没有放到公共域中,因为绝大多数内容还没有完成。如果您对这里的内容感兴趣可以和我们联系!

为软件包进行日志记录

如果我们着手开发一个软件包,而不是一个应用程序,那么应该怎样为其进行日志记录呢?

要解决这个问题,我们必须认识到:

  • 不能采用私有的日志记录方式,要和应用程序的日志记录方式融合到一起
  • 无法预知使用我们软件包的应用程序采用那个具体日志记录实现
  • 无法限制使用我们软件包的应用程序采用某个具体日志记录实现

解决这个问题通常的方法是对日志记录功能进行抽象,然后让客户来定制这种抽象如何映射到具体日志记录实现上。

让客户来定制这种映射增加了客户的工作量,这不利于软件包的流行。如果能够有更多的信息,例如具体日志记录实现的流行程度(依据这样的信息可以提供一些默认的映射)等,我们可以进一步增加软件包的易用性从而改善客户体验。

现在我们有了解决问题的思路,一切看起来还都不错。但是还不够好,因为我们的软件包中包含了许多日志记录功能的抽象,这部分要进行分离。

在Java世界中这种分离已经完成了,那就是Commons logging。我们可以直接使用它来为软件包进行日志记录。

Commons logging对日志记录功能进行了抽象,抽象的结果是Log接口。其中提供了六种日志记录级别,对应着12个日志记录API和6个检测API。

开发Java软件包时Commons logging是一个非常好的选择,因为软件包中的日志记录多比较简单。

开发应用程序时Commons logging也是一个不错的选择,它允许在运行时为应用程序更换具体日志记录实现。不过要是日志记录很复杂,就要考虑使用具体的日志记录实现了,如Log4J等。如果您不熟悉Log4J,那我们建议您阅读一下 使用Log4j进行日志记录

Commons logging不会试图对具体日志记录实现进行初始化和终止,这是具体日志记录实现的职责。

Commons logging依据具体日志记录实现的流行程度提供了一些默认映射,如提供了到Log4J的映射Log4JLogger,提供了到JDK14的映射Jdk14Logger,等等。要了解其它映射的情况,请查阅Commons logging的Javadoc文档

Commons logging不仅提供了一些默认映射,还提供了一个发现机制,这种发现机制也和具体日志记录实现的流行程度相关。这改善了用户体验。如果一个客户使用的是流行的日志记录实现那它几乎什么都不用做就可以使用我们的软件包。从另一个方面来讲,提供默认映射和发现机制弱化了客户自定义映射的需求,这使得很少有人会意识到Commons logging还有自定义映射的能力。设想有一个应用使用了一个很少见的或专有的日志记录实现而Commons logging没有为其提供默认映射,在这种情况下就要自定义映射了。

我们会在下一篇中继续讨论Commons logging。