upd: Changed the chart and code. Expanded the example and description.Read the description of other patterns.
Prehistory
After returning home, after a brief meeting with an old friend, I found that I had left my mobile phone with him, and at the same time, the only alarm clock in the apartment. The situation was complicated by the fact that tomorrow at 8:00 I had to be at work. The option to return for a mobile phone at 11 pm I did not even consider. And the first thing that came to my mind was to write my alarm clock, and using the “Bridge” pattern, which I already had to implement within the framework of the special course. As they say, two birds with one stone ... I think it is not necessary to explain that I went to bed in the morning, but pleased with myself. And in the morning, at exactly 7:00 am, my bridge-alarm clock awakened me triumphantly, playing with fun the tune from TBBT.
')
As I got to this, read under Habrokat.
Problem
Separate the abstraction from the implementation so that both can be changed independently. When using inheritance, the implementation is tightly bound to abstraction, which makes independent modification difficult.
Description
It is impossible to imagine object-oriented programming and analysis without the concept of abstraction and implementation. In addition, modern programming languages ​​contain specialized constructions for describing abstractions and implementations. Any adequate developer, uses abstractions in solving certain problems. For example, java.util.List is a list abstraction, java.util.ArrayList is an implementation of this list based on arrays, java.util.LinkedList is an implementation based on linked lists. At the same time, the only mechanism used when describing abstractions is the inheritance mechanism. In other words, implementations must implement (I apologize for taftology) an abstraction interface.
However, in addition to the basic mechanism for describing abstractions - the mechanism of inheritance (implementation of interfaces), there is another - the application of the “Bridge” pattern.
It would seem, what does not suit the mechanism of inheritance? Why was this pattern invented? It's very simple - collective development. Indeed, in large projects, this is an ordinary thing - programming / designing abstractions and implementations. Moreover, sometimes it is simply necessary to develop / modify these two seemingly related concepts completely independently. When using the inheritance mechanism it is very difficult. Any changes in the abstraction interface should immediately be implemented in the implementation.
So, we separate the abstraction from the implementation using the "Bridge". To do this, we will create a common interface for all implementations, which they (implementations) will implement. In the abstraction interface store the link to the implementation interface. Now we can completely independently modify the abstraction — by refining the abstraction interface and implementation — by implementing the implementation interface. The only thing I wanted to focus on was designing the interfaces of abstraction and implementation. As a rule, the implementation interface contains the simplest methods, while the interface abstraction is higher-level methods, the implementation of which is actually a superposition of the simplest methods from the implementation interface.
Practical task
Implement the bridge alarm clock :) Let the alarm interface interface - AlarmClock, which can start (start), stop (stop) and actually wake up (toWake), the implementation interface - AlarmClockImpl, which describes two methods - ring (ring) and report (notify). Obviously, the toWake method will in turn call these two methods from the implementation. First, it will inform you that “the time has come”, then it will ring. Connect these interfaces by bridge (link to AlarmClockImpl inside AlarmClock). Now we’ll write the AlarmClock clarification — like a “hanging alarm” (LockupAlarmClock) and two implementations of AlarmClockImpl — as an MP3 player’s alarm clock by executing an external system command (ShellMP3AlarmClock) and an MP3 player’s alarm clock, via system libraries (SystemMP3AlarmClock).
Class diagram
It is important to understand that with this approach, the classic notion “realization of abstraction” is difficult to discern. Because both the abstraction and the implementation of abstraction are realized and no one knows where to look for the guilty. In this case, the implementations (in the usual sense of the word) will be all sorts of combinations of refinements of abstractions and implementations of the interfaces of implementations (taftology again). In this case, there are two implementations - it is a hanging alarm playing MP3 through an external command and through the system libraries. If we write a new refinement of abstraction, say, in the form of a demon alarm clock, we get as many as four implementations.

Implementation
The SystemMP3AlarmClock implementations, in the code below, are
not . I added this class to the diagram, only for a better understanding of the pattern.
//
class AlarmClock {
private :
virtual void toWake() = 0;
protected :
/**
It`s our bridge to implementation
*/
AlarmClockImpl *bridge;
public :
virtual void start() = 0;
virtual void stop() = 0;
};
//
class AlarmClockImpl {
public :
virtual void ring() = 0;
virtual void notify() = 0;
};
//
class LockupAlarmClock : public AlarmClock {
private :
WORD hourAlarm; //
WORD minutesAlarm; //
bool waitForWake; //
virtual void toWake();
protected :
public :
LockupAlarmClock(AlarmClockImpl& bridgeImpl, WORD hour, WORD minutes);
virtual void start();
virtual void stop();
};
LockupAlarmClock::LockupAlarmClock(AlarmClockImpl& bridgeImpl, WORD hour, WORD minutes) {
this ->bridge = &bridgeImpl;
this ->waitForWake = false ;
this ->hourAlarm = hour;
this ->minutesAlarm = minutes;
}
// !!! !!
void LockupAlarmClock::toWake() {
this ->bridge->notify();
this ->bridge->ring();
}
// ""
void LockupAlarmClock::start() {
// start lockup process
SYSTEMTIME time;
waitForWake = true ;
while (waitForWake) {
GetLocalTime(&time);
if (time.wHour == this ->hourAlarm && time.wMinute == this ->minutesAlarm) {
waitForWake = false ;
}
Sleep(100);
}
toWake();
}
void LockupAlarmClock::stop() {
// stop lockup process
waitForWake = false ;
}
// , MP3
class ShellMP3AlarmClock : public AlarmClockImpl {
private :
string cmdplay; //
protected :
public :
ShellMP3AlarmClock( const string & cmd);
~ShellMP3AlarmClock();
virtual void ring();
virtual void notify();
};
ShellMP3AlarmClock::ShellMP3AlarmClock( const string & cmd) {
this ->cmdplay = cmd;
}
void ShellMP3AlarmClock::ring() {
// run command
system(cmdplay.c_str());
}
void ShellMP3AlarmClock::notify() {
cout << "ALARMING!" << endl;
}
* This source code was highlighted with Source Code Highlighter .
We continue to study patterns :)
upd: As many here have thought, my goal was to write an alarm clock. This is not true. I just wanted to study the relevant pattern and put it into practice. A forgotten phone only served as an impetus for writing an alarm clock.
upd2: Yes, I could use crown if I really needed an alarm clock.
upd3: Yes, I could use the Windows scheduler.