Definition
Object-oriented design is the discipline of modeling a software system as a set of collaborating objects, each bundling its own state with the behavior that operates on it. The central design questions are which objects should exist, what each is responsible for, and how they depend on one another — decisions that determine whether the resulting system is rigid or adaptable.
A good object-oriented design names the right abstractions, gives each object a single clear purpose, and keeps the dependencies between objects loose enough that the system can change without unraveling. The objects in the running program rarely map one-to-one to objects in the problem domain; part of the craft is inventing intermediary abstractions — strategies, factories, observers — that have no real-world counterpart but make the design more flexible.
Why it matters
How it works
Encapsulation
Encapsulation hides an object's internal representation behind a public interface. Clients interact only through that interface, so the object is free to change how it stores or computes things. This is the first line of defense against coupling: the less a client knows about an object's internals, the less a change to those internals can hurt it.
Inheritance versus composition
There are two ways to reuse behavior. Class inheritance defines a new class in terms of an existing one, reusing the parent's implementation — but it binds the relationship at compile time and exposes the subclass to the parent's internals. Object composition assembles behavior by holding references to other objects and delegating to them at run time. Composition keeps each class focused and lets behavior be reconfigured dynamically, which is why mature object-oriented design favors composition for most reuse.
Programming to an interface
Clients should depend on an abstract type, not a concrete class. When code is written against an interface, any object that conforms can be substituted, which is the mechanism that makes polymorphism and pluggable design possible. This single habit underlies most of the flexibility that object-oriented design promises.