Software design is all about thinking in terms of software components. If you can build these components then you can build the software product.
When we speak of components, we also think in terms of abstraction. Abstraction is the most powerful tool in building software products. Abstraction is about generalising about many similar things and then making a general design for a master component which after tweaking will result in building all these similar components with least effort. At the same time, code once and reuse everywhere principle ensures minimum software defects entering into the software product.
Let us consider an example. Suppose you need to build a component for purchase orders. Your customer tells you that their purchase order contains many variations. Some purchase orders are meant to be used for purchasing goods from regular vendor. Some other type of purchase orders are used for purchase from irregular vendors. Some other type of purchase orders are used for internal purchases e.g. getting semi finished goods from one plant to another plant. Due to these variations, fields contained on a purchase order are different depending on the type of purchase order.
If you will create diferen components for different types of purchase orders? Most likely you will create a common component which may represent a general purchaase order. Later you can create specific components for each type of purchase order.
the generalization used in creating a general purchase order is an example of abstraction. Using abstraction you can reuse your design and your code. In our example when classes are designed for purchase orders then you can create a super class for the general purchase order and extend it to create sub classes for each type of purchase order.