鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 手机系统开发 > J2ME > >

OO Design Recommendations for J2EE Applications

来源:互联网 作者:佚名 时间:2015-09-25 05:41
OO Design Recommendations for J2EE Applications j2ee应用推荐的oo设计 It's possible to design a J2EE application so badly that, even if it contains beautifully written Java code at an individual object level, it will still be deemed a failu


OO Design Recommendations for J2EE Applications


It's possible to design a J2EE application so badly that, even if it contains beautifully written Java code at an individual object level, it will still be deemed a failure. A J2EE application with an excellent overall design but poor implementation code will be an equally miserable failure. Unfortunately, many developers spend too much time grappling with the J2EE APIs and too little ensuring they adhere to good coding practice. All of Sun's J2EE sample applications seem to reflect this.

In my experience, it isn't pedantry to insist on adherence to good OO principles: it brings real benefits.



OO design is more important than any particular implementation technology (such as J2EE, or even Java). Good programming practices and sound OO design underpin good J2EE applications. Bad Java code is bad J2EE code.


Some "coding standards" issues – especially those relating to OO design – are on the borderline between design and implementation: for example, the use of design patterns.


The following section covers some issues that I've seen cause problems in large code bases, especially issues that I haven't seen covered elsewhere. This is a huge area, so this section is by no means complete. Some issues are matters of opinion, although I'll try to convince you of my position.


Take every opportunity to learn from the good (and bad) code of others, inside and outside your organization. Useful sources in the public domain include successful open source projects and the code in the core Java libraries. License permitting, it may be possible to decompile interesting parts of commercial products. A professional programmer or architect cares more about learning and discovering the best solution than the buzz of finding their own solution to a particular problem.


Achieving Loose Coupling with Interfaces


The "first principle of reusable object-oriented design" advocated by the classic Gang of Four design patterns book is: "Program to an interface, not an implementation". Fortunately, Java makes it very easy (and natural) to follow this principle.




Program to interfaces, not classes. This decouples interfaces from their implementations. Using loose coupling between objects promotes flexibility. To gaim maximum flexibility, declare instance variables and method parameters to be of the least specific type required.


Using interface-based architecture is particularly important in J2EE applications, because of their scale. Programming to interfaces rather than concrete classes adds a little complexity, but the rewards far outweigh the investment. There is a slight performance penalty for calling an object through an interface, but this is seldom an issue in practice.


A few of the many advantages of an interface-based approach include:


  • The ability to change the implementing class of any application object without affecting calling code. This enables us to parameterize any part of an application without breaking other components.

  • 改变任何应用对象的实现类而不需要影响调用代码的能力。这可以使得我们参数化任何部分的应用程序而不需要打破其他的组件。

  • Total freedom in implementing interfaces. There's no need to commit to an inheritance hierarchy. However, it's still possible to achieve code reuse by using concrete inheritance in interface implementations.

  • 完全自由的实现接口。这儿不需要指定一个继承层次。然而,它任然可能完成代码重用用具体的继承层次在接口实现中。

  • The ability to provide simple test implementations and stub implementations of application interfaces as necessary, facilitating the testing of other classes and enabling multiple teams to work in parallel after they have agreed on interfaces.

  • 提供简单的测试实现和应用接口存根实现的必要能力,促进其他的类的测试和是多个团队平行的工作在他们同意了接口后。

Adopting interface-based architecture is also the best way to ensure that a J2EE application is portable, yet is able to leverage vendor-specific optimizations and enhancements.


Interface-based architecture can be effectively combined with the use of reflection for configuration (see below).


Prefer Object Composition to Concrete Inheritance


The second basic principle of object-oriented design emphasized in the GoF book is "Favor object composition over class inheritance". Few developers appreciate this wise advice.


Unlike many older languages, such as C++, Java distinguishes at a language level between concrete inheritance (the inheritance of method implementations and member variables from a superclass) and interface inheritance (the implementation of interfaces). Java allows concrete inheritance from only a single superclass, but a Java class may implement any number of interfaces (including, of course, those interfaces implemented by its ancestors in a class hierarchy). While there are rare situations in which multiple concrete inheritance (as permitted in C++) is the best design approach, Java is much better off avoiding the complexity that may arise from permitting these rare legitimate uses.

不像许多年老的语言,例如c++,java区分一个语言层次在类继承(从父类中继承方法和成员变量)和接口继承(实现接口)。java仅仅允许单继承,但是java类可以实现任意数量的接口(包含,当然,在一个类的层次上这些接口被实现)。 然而有很少的情形下有多类继承(例如在c++中允许)是最好的设计方式,java更好的避免了允许这些罕见的合法使用的复杂性。

Concrete inheritance is enthusiastically embraced by most developers new to OO, but has many disadvantages. Class hierarchies are rigid. It's impossible to change part of a class's implementation; by contrast, if that part is encapsulated in an interface (using delegation and the Strategy design pattern, which we'll discussed below), this problem can be avoided.


Object composition (in which new functionality is obtained by assembling or composing objects) is more flexible than concrete inheritance, and Java interfaces make delegation natural. Object composition allows the behavior of an object to be altered at run time, through delegating part of its behavior to an interface and allowing callers to set the implementation of that interface. The Strategy and State design patterns rely on this approach.


To clarify the distinction, let's consider what we want to achieve by inheritance.


Abstract inheritance enables polymorphism: the substitutability of objects with the same interface at run time. This delivers much of the value of object-oriented design.


Concrete inheritance enables both polymorphism and more convenient implementation. Code can be inherited from a superclass. Thus concrete inheritance is an implementation, rather than purely a design, issue. Concrete inheritance is a valuable feature of any OO language; but it is easy to overuse. Common mistakes with concrete inheritance include:


  • Forcing users to extend an abstract or concrete class, when we could require implementation of a simple interface. This means that we deprive the user code of the right to its own inheritance hierarchy. If there's normally no reason that a user class would need it's own custom superclass, we can provide a convenient abstract implementation of the method for subclassing. Thus the interface approach doesn't preclude the provision of convenient superclasses.

  • 强迫用户去扩展一个抽象类或具体类,当我们能要求一个简单的接口实现时。这意味着我们剥夺了用户代码的权利对它自己的类继承。如果通常没哟原因一个用户类将需要它自己的超类,我们将提供一个方便的抽象实现方法为子类。因此接口途径并没有预先包含便利的父类的规范。

  • Using concrete inheritance to provide helper functionality, by subclasses calling helper methods in superclasses. What if classes outside the inheritance hierarchy need the helper functionality? Use object composition, so that the helper is a separate object and can be shared.

  • 用类继承去提高帮助功能,用子类调用在父类中的帮助方法。如果这个类在这个继承体系的外部需要这个帮助功能呢?用对象组合,以至于这个帮助类是一个分离的对象能被分享。

  • Using abstract classes in place of interfaces. Abstract classes are very useful when used correctly. The Template Method design pattern (discussed below) is usually implemented with an abstract class. However, an abstract class is not an alternative to an interface. It is usually a convenient step in the implementation of an interface. Don't use an abstract class to define a type. This is a recipe for running into problems with Java's lack of multiple concrete inheritance. Unfortunately, the core Java libraries are poor examples in this respect, often using abstract classes where interfaces would be preferable.

  • 用抽象类代替接口。抽象类是非常有用的当我们考虑正确。这个模板方法设计模式(在下面讨论)通常用一个抽象类实现。然而,,一个抽象类不是唯一的选择去替换接口。它通常是一个便利的步骤在接口的实现中。不要用一个抽象类去定义一个类型。这是因为java缺乏多继承。不幸的是,java核心包在这方面的例子太少了,经常用抽象类在接口可能是更好的地方。

Interfaces are most valuable when kept simple. The more complex an interface is, the less valuable is modeling it as an interface, as developers will be forced to extend an abstract or concrete implementation to avoid writing excessive amounts of code. This is a case where correct interface granularity is vital; interface hierarchies may be separate from class hierarchies, so that a particular class need only implement the exact interface it needs.




Interface inheritance (that is, the implementation of interfaces, rather than inheritance of functionality from concrete classes) is much more flexible than concrete inheritance.


Does this mean that concrete inheritance is a bad thing? Absolutely not; concrete inheritance is a powerful way of achieving code reuse in OO languages. However, it's best considered an implementation approach, rather than a high-level design approach. It's something we should choose to use, rather than be forced to use by an application's overall design.