Observer Pattern is defined by the 'Gang of Four' Design Patterns book as a "one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically".
They also say that the Observer pattern should be used in any of the following situations:
When an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently.
When a change to one object requires changing others, and you don't know how many objects need to be changed.
When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.
On Adam Stroud Android Database Best Practices book it states that "the Cursor class provides the methods that expose the Observer pattern to a source of data. And, by using these methods, it is possible to respond to data changes using the Observer Pattern rather than polling the database for changes, which can be inefficient":
Similarly, by using a ContentProvider, we can use a ContentResolver client object to access the data from the Content Provider and then register a ContentObserver to listen to the change of data behind the URI the observer was registered for.
So, as the Subject object in the Observer pattern, ContentResolver has the methods that, by my thinking, are almost the same:
registerContentObserver() of ContentResolver is Attach() from Subject
unregisterContentObserver() of ContentResolver is Dettach() from Subject
notifyChange() of ContentResolver is Notify() from Subject
So, my question is, if the three components of a ContentProvider (ContentProvider, ContentResolver, and ContentObserver) are by themselves an implementation of the Observer pattern?
Yes and no.
Yes, because the pattern of interaction described in Observer exists in these classes in equivalent semantic form.
No, because there is so much more going on in those classes than just Observer. Between them they also handle data persistence, cross-process communication, synchronous vs asynchronous updates and much more.
The Observer pattern, and many others by GoF, were identified in part to enable composition and code reuse through lightweight mixin-type implementations. This could be done in C++, much less so in Java.
Java of course for many reasons tends towards large, heavyweight classes that never do just one thing. In Java, you could not just borrow the Observer pattern bits from those classes and use them elsewhere. You would instead reimplement the pattern.
So- these classes implement the pattern, but they are not necessarily a model implementation of the pattern, in alignment with the original spirit of GoF.