Difference between class scope and object scope design patterns

design-patterns

Apparently design patterns have a ton of classifications. One I am struggling with is whether or not the pattern is a class scoped pattern or an object scoped pattern. Of course no documentation exists on the differences between the two, so I'm asking your opinion.

The GoF book defines it as:

"Class patterns deal with relationships between classes and their subclasses. These relationships are established through inheritance, so they are static-fixed at compile-time. Object patterns deal with object relationships, which can be changed at run-time and are more dynamic. Almost all patterns use inheritance to some extent. So the only patterns labelled "class patterns" are those that focus on class relationships. Note that most patterns are in the object scope."

Problem is, there are only class relationships as an object is nothing without its class. I've never heard of "object relationships" outside of this book.

Best Answer

This boils down to composition vs. inheritance.

Let's take a look at one pattern that you can do in both ways.

The adapter pattern is, as the name implies, an adapter between two classes that are otherwise incompatible.

Say you write a 3D engine and you need a Point class. You have your Point all ready and it kind of works, but then you find another class OtherPoint in some library that does everything your class should be doing in a nicer way, but its methods have different names. Your 3D engine expects your Point class.

What can you do to make both classes compatible in order to use OtherPoint class?

  1. Point extends OtherPoint inheritance for the win. Point receives all the functionality it needs. The methods specific to your engine that Point declares simply call the corresponding ones from OtherPoint. This is the class pattern style of the adapter.
  2. On the other hand, you could do Point(OtherPoint constructorParameter) to receive an OtherPoint object. The idea is similar: the Point methods now don't delegate to the methods it received via inheritance but to the object it received as a parameter in the constructor. This is the object pattern style of the adapter. This is a comparable to the wrapper pattern.

How does that explain the GoF statement(s)?

"Class patterns [...] are static-fixed at compile-time.

By saying Point extends OtherPoint you say that a Point is a OtherPoint. It's a plain old simple inheritance chain. You cannot change them at run time.

Object patterns [...] which can be changed at run-time and are more dynamic

By saying Point(OtherPoint constructorParameter) you say that a Point has a OtherPoint. Maybe you find out that this library has an even fancier class, i.e. FancierOtherPoint extends OtherPoint. You can pass that to Point as well. In fact you can pass any sublcass of OtherPoint to Point, because of polymorphism.

Maybe FancierOtherPoint only works on certain hardware and you have to check for that hardware at run time. With the object pattern style of the adapter, you can do exactly that: decide dynamically what class to use.


I've never heard of "object relationships" outside of this book.

"object relationships" is not special phrase. It means exactly what is says: relationships between objects. Design patterns are just names for common ways to define relationships between objects.

If I were to say "3.14159265359..." you'd probably stop me to ask if I mean "pi". Now if you were to tell me you "inherit from that one class to make things compatible and delegate methods and..." I would stop you to ask if you mean the adapter pattern.

It simplifies communication and everybody has a rough understanding of what the conversation is about without explaining everything in full detail.