Consider the simple class hierarchy of the design model in Figure 12.1 above, showing a disjoint segmentation of the class `Book`

. In such a case, whenever there is only one level (or there are only a few levels) of subtyping and each subtype has only one (or a few) additional properties, it's an option to re-factor the class hierarchy by merging all the additional properties of all subclasses into an expanded version of the root class such that these subclasses can be dropped from the model, leading to a simplified model.

This Class Hierarchy Merge design pattern comes in two forms. In its simplest form, the segmentations of the original class hierarchy are **disjoint**, which allows to use a **single-valued** `category`

attribute for representing the specific category of each instance of the root class corresponding to the unique subclass instantiated by it. When the segmentations of the original class hierarchy are not disjoint, that is, when at least one of them is **overlapping**, we need to use a **multi-valued** `category`

attribute for representing the set of types instantiated by an object. We only discuss the simpler case of Class Hierarchy Merge re-factoring for disjoint segmentations, where we take the following re-factoring steps:

Add an

**enumeration datatype**that contains a corresponding enumeration literal for each segment subclass. In our example, we add the enumeration datatype`BookCategoryEL`

.Add a

`category`

attribute to the root class with this enumeration as its range. The`category`

attribute is mandatory [1], if the segmentation is complete, and optional [0..1], otherwise. In our example, we add a`category`

attribute with range`BookCategoryEL`

to the class`Book`

. The`category`

attribute is optional because the segmentation of`Book`

into`TextBook`

and`Biography`

is incomplete.Whenever the segmentation is

**rigid**, we designate the`category`

attribute as**frozen**, which means that it can only be assigned once by setting its value when creating a new object, but it cannot be changed later.Move the properties of the segment subclasses to the root class, and make them

**optional**. We call these properties, which are typically listed below the`category`

attribute,**segment properties**. In our example, we move the attributes`subjectArea`

from`TextBook`

and`about`

from`Biography`

to`Book`

, making them optional, that is [0..1].Add a constraint (in an invariant box attached to the expanded root class rectangle) enforcing that the optional subclass properties have a value if and only if the instance of the root class instantiates the corresponding category. In our example, this means that an instance of

`Book`

is of category "TextBook" if and only if its attribute`subjectArea`

has a value, and it is of category "Biography" if and only if its attribute`about`

has a value.Drop the segment subclasses from the model.

In the case of our example, the result of this design re-factoring is shown in Figure 12.7 below. Notice that the constraint (or "invariant") represents a logical sentence where the logical operator keyword "IFF" stands for the logical equivalence operator "if and only if" and the property condition` prop=undefined `

tests if the property `prop`

does not have a value.