7
$\begingroup$

The slides from my course in software architecture hints that these are seperate terms, but I can't seem to find the difference. Aren't all of them just translating interfaces?

$\endgroup$
  • 3
    $\begingroup$ I think you should offer some more context. $\endgroup$ – Raphael Jun 8 '12 at 18:39
  • 2
    $\begingroup$ Cross-posted at about the same time to stack overflow. $\endgroup$ – jmad Jun 8 '12 at 18:50
8
$\begingroup$

It was very common for early patterns research to put a lot of emphasis on the "intended use" of a pattern, over and above any structural differences in the implementation. Then, people who were at that stage of architectural maturity where they were "doing patterns because patterns is what you do" developed long, often elaborate explanations on why these alleged differences were important.

However, research has shown that the structure is really all that matters, because the semantic distinctions:

  • have no formal distinctions, even in the mathematical treatment of type theory
  • are not enforceable without syntactic differences in developing the type relations (compiler needs something to enforce)
  • therefore change with changing requirements
  • and should not be forced not to change, as reuse is the point of good architecture

So much of those large discussions on why strategy is different than state have turned out quite labored, unconvincing, ineffectual, and slightly humorous as the years have moved on.

My suggestion is to ignore any "is used for" discussion at all and completely focus on the type relationships. If you do that, then you will find that (depending on your particular definition of these patterns, but fairly standard here)

Mediator > Bridge > Adapter

where the > relation should be read as "is implemented using". Adapter is a functional relationship between three or more types around on one abstraction tree. Bridge and Mediator are functional relationship between four or more types around two abstraction trees, defining an interface between the abstraction trees. Mediator adds to the type coupling usage relationships between concrete nodes of the abstraction trees.

Typically, Mediator is a bad pattern (antipattern) that doesn't scale well and causes an application to become monolithic. It is used very frequently because people read what it does and go "oh, I need that" and use a pattern becasue, as above, well, patterns are "what you use". They may be an intermediate step while decoupling a heavily coupled application during refactoring, but typically if you are making that step, full decouple to Bridge (with a factory) is indicated and just as easy.

$\endgroup$
  • $\begingroup$ which of the other "standard" pattern are also antipatterns, in your opinion? $\endgroup$ – Novellizator Apr 2 '16 at 23:05
  • $\begingroup$ I think the one that is most common to bring up is Singleton. You should never force a semantics on your objects (like only one instance existing) that is not necessary to force (only instantiate once if that's what you need). It's usually used to make access "easy" though, and just pollutes global space and hides dependency relations. $\endgroup$ – ex0du5 Apr 3 '16 at 18:34
  • $\begingroup$ But the one that really gets me isn't seen in GoF, but is a very common pattern in computing: polling. The only time this is every "required" is badly designed hardware. It is never needed for software monitoring yet persists due to bad protocol design, interface laziness, etc.. One should never waste timeslices not knowing you will find anything useful, and polling has a built-in latency that is rarely useful in this form. Latency can be useful in debouncing transitions, but that should only occur once a transition has been determined. We should strive to be event driven. $\endgroup$ – ex0du5 Apr 3 '16 at 18:40
  • $\begingroup$ Really, though, I think we shouldn't think in patterns except as recognition. Engineers should really just design what comes from their domain language. That's where the types and their relations come from. Then, just keep good architecture in mind - stuff like the Open/Closed principle, reuse, contain rather then inherit, inheritance is for abstract interface bases very few layers deep (preferably just one base except where polymorphic interfaces naturally have structure), state machines for state [event-driven] lifetimes, etc.. That drives picking the right type relations, not patterns. $\endgroup$ – ex0du5 Apr 3 '16 at 18:48
  • $\begingroup$ Could you point to the research, that "has shown that the structure is really all that matters"? $\endgroup$ – PsiX Jul 18 '16 at 13:15
6
$\begingroup$

Generally there are a lot of notions of interfaces in computer science. You should probably say that you are talking about about design patterns. In the corresponding Wikipedia article, there is a classification of different patterns that clears things up:

  • The mediator pattern is behavioral (about communication between interfaces) and unifies several interfaces, notably their way of communicating together much like an actual mediator.

  • The other two are structural (actually comparing interfaces):

    • the wrapper/adapter pattern is focused on making an interface compatible, for example if a client uses different conventions;

    • the bridge pattern is about separating what the class is supposed to do (abstraction) from how it actually does it (implementation). That way you can use the abstraction without knowing how it is implemented, which is useful when the code changes (for both sides).

$\endgroup$
5
$\begingroup$

There are differences. Most of them are subtle enough that you wouldn't care, but they generally differ either in intent or in implementation. The overarching idea is to provide class A with access to the functionality of class B, without A having to care that it's B doing the work (so that a class C can be substituted without any of these objects having to change). This idea is typically called "loose coupling" and is generally to be encouraged..

  • A Bridge is the most basic definition of the intent to decouple A and B; that, in and of itself, is the purpose. A instead knows about an interface I, which B implements. A class C can also implement I and can be substituted freely.

  • A "wrapper" or Adapter is typically written with the intention of changing the interface of B to match the set of functionality that A expects of its dependency I. If A expects I to have a "DoThis()" method with three parameters, but the method with the functionality A needs on B is actually named "DoThat()" and takes a parameter, an Adapter W can be written that is dependent on B (or B's interface IB), implements I, and calls B.DoThat() from its own DoThis() method (passing the parameter, which it can gain without A's knowledge). If C is needed instead and differs from B, a different Adapter W2 can be written which takes a C and also implements I, so A, W, I, B, and C don't have to change.

  • Mediator patterns are basically an Adapter used as a Bridge. A Mediator is its own object M, which knows about B and is given to A. When A calls methods on M, those calls are passed through to B. M may do additional things, such as providing two-way communication between A and B. B may be required to change A's data or call its members, but cannot know about A itself. M may resolve this "circular" or "many to many" dependency structure by allowing both A and B to depend on M.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.