Three measures to improve the reusability of Java code
(Panasonic May, 2001 00:08) This article introduces three modifications to existing code to improve its reusability, which is: rewriting the instance method of the class, change the parameter type to the interface, and select the easiest Parameter interface type. Action 1: An instance of rewriting classes is not accurate code reuse through class inheritance, so it is not the most ideal code reuse mechanism. In other words, if all methods and data members of the entire class are not inherited, we cannot retrieve a single method in this class. Inheritance always brings some extra methods and data members, which always make the code to complicate a method in the reuse class. In addition, derived class has further compacted the code to the parent class: which may affect the child class; modify any class in the parent class or subclass, which method is hard to remember. Subclass coverage Which method is not covered by subclasses; Finally, whether the coverage method in the subclass is to call the corresponding method in the parent class is sometimes not obvious. Any method, as long as it is a single conceptual task, it should be the preferred reusable code. In order to reuse this code, we must return to the process-oriented programming mode, remove the instance method of the class into a global process. In order to improve the reusability of this process, the process code should be written like a static tool method: it can only use its own input parameters, can only call other global processes, and any non-local variables cannot be used. This limitation on external dependencies simplifies the application of the process, making the process easily used anywhere. Of course, since this organizational mode always makes the code a clearer structure, even if the code that does not consider the reuse, it can also benefit from it. In Java, the method cannot be separated from the class and alone. To do this, we can organize relevant process organizations an independent class and define these processes as a common static method. For example, for the following class:
Class Polygon {. Public Int getImeter () {...} public boolean isconvex () {...} public boolean containspoint (POINT P) {...}.} We can rewrite it:
class Polygon {public int getPerimeter () {return pPolygon.computePerimeter (this);..} public boolean isConvex () {return pPolygon.isConvex (this);} public boolean containsPoint (Point p) {return pPolygon.containsPoint (this, p);}.} where PPOLYGON is:
class pPolygon {static public int computePerimeter (Polygon polygon) {...} static public boolean isConvex (Polygon polygon) {...} static public boolean containsPoint (Polygon polygon, Point p) {...}} class name from PPOLYGON can be seen that the process of this class is mainly related to the object of the Polygon type. P in front of the name indicates that the unique purpose of this class is to organize public static processes. In Java, the name of the class is a non-standard approach at lowercase letters, but it does not provide the functionality of the normal Java class like PPLOYGON. That is, it does not represent a type of object, which is just a mechanism for the Java language organizational code. In this example, the ultimate effect of the change is that the customer code that applies the Polygon function does not have to inherit from Polygon. The function of the Polygon class is now available in the process of the PPOLYGON class. Customer code only uses the code you need, there is no need to care about the features you don't need in the Polygon class. But it does not mean that the role of this new process programming is weakened. On the contrary, in the process of organizational and package object data, the class has played an indispensable role, and as this article will be introduced, the ability to achieve polymorphism through multiple interfaces has also brought superior code. Reuse support. However, since the instance method package code function is not the preferred code reuse means, it is not the best to achieve code reuse and polymorphism support through class inheritance. Action 2: Change the parameter type change to the interface as indicated in "Build User Interfaces for Object-Oriented Systems", in object-oriented programming, the real point of code reuse is the use of polymorphisms through the interface parameter type. Not through class inheritance: "... we have reused the code reuse through the interface instead of class programming. If all the parameters of a method are references to some known interfaces, then this method can operate some objects: When we write the code of the method, the class of these objects does not exist. From a technical statement, it is possible to reuse the method, not the object that passes to the method. "Apply Holub's view on the results obtained by" Measures " When a block code can be written as a stand-alone global process, as long as it is changed to all types of parameters to interface, we can further increase its reusable ability. After this change, the parameters of the process can be objects that implement all classes of the interface, not just the objects created by the original class. Thus, the process will be able to operate a large number of object types that may exist. For example, suppose there is a global static method: Static Public Boolean Contains (Rectangle Rect, INT X, INT Y) {...} This method is used to check if the specified point is included inside the rectangle. In this example, the type of RECT parameter can be changed from the Rectangle class to the interface type, as shown below:
Static Public Boolean Contains (Rectangular Rect, Int x, int y) {...} and the Rectangular interface definition is:
Public interface rectangular {rectangle getBounds ();} Now, all objects created as rectangular classes (ie, authentication of the Rectangular Interface) can be used as a Rect parameter supplied to prectangular.contains (). We have better reusability by relaxing parameter type limits. However, for the above example, the getBounds method of the Rectangular interface returns Rectangle, and you may be suspected whether it is really worth it. In other words, if we know that the object of the incoming process will return a Rectangle when being called, why not directly enter the rectangle replacement interface type? The reason why the reason is not doing, the most important reason is related to the collection. Let us assume that there is such a method: static public boolean allanyoverlapping (Collection Rects) {...} This method is used to check whether any rectangular object in a given collection overlaps. Inside this method, when we use a loop to access the individual objects in the collection, if we can't bring objects Cast to the interface type, which is the roof of Rectangular, and how can I access the rectangular area of the object? The only choice is to bring the object Cast as its unique class form (we know that it has a method to return a rectangle), which means that the method must know the type of object it operate in advance, so that the reuse of the method is limited to those objects Types of. And this is exactly what you want to avoid in front of this measures! Action 3: Select the simplest parameter interface type When implementing the second measure, which interface type should I choose to replace a given class? Which interface is fully satisfied with the demand for the parameters while also has the least amount of extra code and data. The more simple interfaces that describe the parameter object require, the larger the chance to implement the interface, thereby, the more the objects can be used as the parameters. From the following example, you can easily see this:
Static Public Boolean Areoverlapping (Window Window1, Window Window2) {...} This method is used to check whether the two windows (assuming is a rectangular window) overlap. If this method only requires the rectangular coordinates of the two windows from the parameters, the corresponding simplification of these two parameters is a better choice:
Static Public Boolean AreoverLapping (Rectangular Rect1, Rectangular Rect2) {...} The above code assumes that the Window type implements the Rectangular interface. After the change, we can reuse the functions of this method for any rectangular object. Sometimes there may be a case where the interface describing the parameter needs has too many methods. At this point, we should define a new public interface in the global namespace for other code reuse that faces the same problem. When we need to use parameters like a function pointer in the C language, create a unique interface description parameter requirement is the best choice. For example, suppose you have the following process:
Static Public Void Sort (List List, SortComparison CoMP {...} This method uses the comparison object CoMP provided in the parameters, by comparing the object sorting list list in the given list List. The only requirement for the Sort is to call a method to compare. Therefore, SortComparison should be only an interface with one way: