Chapter 8. Generalization
Generalization is the transformation of specific code into general-purpose code. The production of generalized code frequently occurs as a result of refactoring. All seven refactorings in this chapter yield generalized code. The most common motivation for applying them is to remove duplicated code. A secondary motivation is to simplify or clarify code.
Form Template Method (205) helps remove duplication in similar methods of subclasses in a hierarchy. If the methods perform roughly the same steps, in the same order, yet the steps are slightly different, you can separate what varies from what is generic by producing a superclass method known as a Template Method [DP].
Extract Composite (214) is an application of the refactoring Extract Superclass [F]. It's applicable when a Composite [DP] has been implemented in multiple subclasses of a hierarchy with no good reason. By extracting a Composite to a superclass, the subclasses share one generic implementation of the Composite.
If you have some code for handling one object and separate code for handling a group of the same objects (usually in some collection), Replace One/Many Distinctions with Composite (224) will help you produce a generic solution that handles one or many objects without distinguishing between the two.
Replace Hard-Coded Notifications with Observer (236) is a classic example of replacing a specific solution with a general one. In this case, there is a tight coupling between objects that notify and objects that get notified. To allow instances of other classes to be notified, the code can be refactored to use an Observer [DP].
An Adapter [DP] provides another way to unify interfaces. When clients communicate with similar classes using different interfaces, there tends to be duplicated processing logic. By applying Unify Interfaces with Adapter (247), clients may interact with similar classes using a generic interface. This tends to pave the way for other refactorings to remove duplicated process logic in the client code.
When a class acts as an Adapter for multiple versions of a component, library, API, or other entity, the class usually contains duplication and often lacks a simple design. Applying Extract Adapter (258) produces classes that implement a common interface and adapt a single version of some code.
The final refactoring in this chapter, Replace Implicit Language with Interpreter (269), targets code that would be better designed were it to use an explicit language. Such code often uses numerous methods to accomplish what a language can do, only in a far more primitive and repetitive way. Refactoring such code to an Interpreter [DP] can yield a general-purpose solution that is more compact, simple, and flexible.