Talk:Bridge pattern

From Wikipedia, the free encyclopedia
Jump to: navigation, search
WikiProject Java (Rated Start-class, Low-importance)
WikiProject icon This article is within the scope of WikiProject Java, a collaborative effort to improve the coverage of Java on Wikipedia. If you would like to participate, please visit the project page, where you can join the discussion and see a list of open tasks.
Start-Class article Start  This article has been rated as Start-Class on the project's quality scale.
 Low  This article has been rated as Low-importance on the project's importance scale.
 
Note icon
This article has been automatically rated by a bot or other tool because one or more other projects use this class. Please ensure the assessment is correct before removing the |auto= parameter.
WikiProject Computer science (Rated Start-class, Low-importance)
WikiProject icon This article is within the scope of WikiProject Computer science, a collaborative effort to improve the coverage of Computer science related articles on Wikipedia. If you would like to participate, please visit the project page, where you can join the discussion and see a list of open tasks.
Start-Class article Start  This article has been rated as Start-Class on the project's quality scale.
 Low  This article has been rated as Low-importance on the project's importance scale.
 

Too Technical[edit]

Even with the example, this article is impenetrable. Some of the problem may just be bad grammar/phrasing, but since I don't understand what it's trying to say I can't fix it myself. 18.24.0.120 04:23, 4 Dec 2003 (UTC)

The diagram and the accompaning Java code do not match. According to the code the arrow from Abstraction to Implementor is actually from RefinedAbstraction to Implementor.

C++[edit]

Sample for C++ bridge pattern is missing.

Code Added for C++[edit]

Added code for C++ but als also derived another class from the Abstraction to demonstrate the interchangebility - the main purpose of this Design Pattern. For the C++ code, the aggregate from Abstraction to Implementor is correct. The code for C# and Java isn't (July 11th, 2006).

Why is the c++ code too unnecessarily obfuscated. Why do we need to have a vector of shapes just to show how it works on 2 different types of circles. I don't think the reader cares about using iterators to traverse a container, he/she wants to see how to use the bridge pattern. Also, what is std::mem_fun and std::bind2nd doing here? and stdafx.h is not a standard header. They don't help show what a bridge is and also confuses a reader!
I have rewritten the code using the same ideas as all of the other ones. It is more readable.--Michael miceli (talk) 05:57, 6 April 2008 (UTC)



Vladimir Bosnjak 10:12, 12 July 2006 (UTC)

C# Code now compiles[edit]

Made the C# code compilable, aggregate still incorrect.

Removed comment on C++ implementation[edit]

Somebody added a line that the C++ code isn't the bridge pattern. It sure is - only more efficiënt implemented. The poster/editor noted that a variable is "pushed up" (whatever that means). Please note that I implemented more abstract abstractions. That's what abstract classes are for! Please, next time, start a tech discussion first before editing the related wiki-page. Vladimir Bosnjak 18:45, 22 September 2006 (UTC)

What Needs To Be Done?[edit]

This article still seems to be too technical. That might be the case easely indeed for some or many. -->>What exactly needs to be done to make it more accessible? I could add a non-software image to visualize the "car example". I could add even more images, refining the steps. I could do a lot more in general. First of all I'd like to see a quick tutorial on how to add images to a wiki page. If someone is willing, please move to my talk-page and help me out with that part. Currently the "wiki manual" on this subject is overwhelming. My time is limited I'm affraid to read it all. I believe a detailed explanation on the details (e.g. code) is out of place. Yet I do agree that more detailed explanation is required. However, this needs teamwork. More insights on that later. Vladimir Bosnjak 20:15, 22 September 2006 (UTC)Vladimir Bosnjak 20:07, 22 September 2006 (UTC)

I recommend deleting the current "Car abstraction" example, as it is incorrect. A road is not an implementation of a car. For that matter, I would avoid using any automotive analogies here. Consider a real-world bridge-- i.e., a structure allowing a road (and therefore cars) to pass over an obstruction. This has little to do with the Bridge pattern, so examples involving cars and roads are likely to just confuse the reader. 14-JUN-2007 Mahler3 21:17, 15 June 2007 (UTC)

I tagged the example as being too confusing. I think it would make more sense if only two examples were given, instead of listing two, and then going into four or so examples with the overly complicated drawing api example. Car->Jaguar Car->Mercedes. Shape->Circle Shape->Square. --Odie5533 03:29, 2 August 2007 (UTC)

Nallap 11:54, 24 October 2007 (UTC)



OK, since the car example has persisted for many months despite it being incorrect and confusing, and no one has defended it, I finally decided to just get rid of it. Honestshrubber (talk) 18:41, 7 November 2008 (UTC)

Is the UML notation wrong for the implementation of the Implementor interface?[edit]

Isn't an implementation of an interface supposed to be a dashed line with an white arrow head? Right now the ConcreteImplementor connects to the Implementor with a solid line with a white arrow head.

Suggestions for changes for Car abstraction:[edit]

The Car example needs some changes as it does not explain the pattern practically. The change I would suggest is as follows.

Car is an abstraction and may be the refined abstraction of car can be Mercedes Make-I (e.g C-class) and Make-II (E-class).Then I totally disagree with Road as the implementation as it is too generic/amateuristic and not a very good real life example. I would suggest the actual implementation of the car can be Engine as it is the heart of any car. So refined implementation can be some thing like a Petrol Engine implementation and a diesel engine implementation. More refining can be done here something like 2-valve engine, 4,6,8 valve engines etc. Any feed back? Also this requires a total revamp of the examples in all languages. I can take care of C++ and C#. Let me know if this is OK.

Does the Shape example at all justify the Bridge Pattern[edit]

I find it difficult to see the light when it comes to the Bridge Pattern. The most common example I see is the Shape example which is also used here. I can easily understand the example, but I find the solution using the Bridge Pattern complete silly.

Using the Bridge Pattern each shape instance is tied to a certain Drawing API. But that seems silly to me; why should shapes be bound to a media at all?

Many places including here the Bridge Pattern is related to working on several operating systems. But can you imagine that some of the shapes in a single running instance of program is on one operating system while others are on another operating system? I cannot, and therefore it seems strange that each shape should have an individual member signifying the operating system (using a Singleton pattern containg a strategy (cf. Strategy Pattern) seems more appropriate in this case).

If facing the problem of drawing using several different APIs in a single running instance of a program. I would use a different pattern (don't know if it has a name). Instead of tying each shape to a drawing API, I would supply the Drawing API to the draw operation. Using the C++ example the main code would look like this:

//The Client.
// -->> int main() merely demonstrates the interchangebility.
int main()
{
  Shape* TheShape[4]; //2 shapes x 2 implementations = 4 client-options.
  DrawingAPI* DA[2]; //2 Implementations.
  DA[0] = new OpenGL;
  DA[1] = new DirectX;

TheShape[0] = new Circle(1, 2, 7.5); TheShape[0]->Draw(DA[0]); //Draw circle with OpenGL
TheShape[1] = new Circle(5, 7, 27.5); TheShape[1]->Draw(DA[1]); //Draw circle with DirectX
TheShape[2] = new Square(10, 14); TheShape[2]->Draw(DA[0]); //Draw square with OpenGL
TheShape[3] = new Square(2.9, 80); TheShape[3]->Draw(DA[1]); //Draw square with DirectX
//Give back allocated memory. delete DA[0], DA[1]; delete TheShape[0], TheShape[1], TheShape[2], TheShape[3];
return 0; }

Another reason that this makes more sense is that the "Drawing API" in this case could also represent the media, so that you can draw the same shapes in several windows and on a printer, etc.

While I beleive I understand the Bridge Pattern, I still lack an example that justifies its use.

Thomas Linder Puls, Prolog Development Center, Denmark

One can't say. No real analysis has been provided to start with. But I don't believe the requirement as defined in the article (multiple shapes interchanged with multiple API's) is a good practical example. I agree with you on that. Interchanging shapes with devices (windows, forms, printers etc.) is a much better example.
I think that the one and only strength of this pattern lies in it's ability to demonstrate how multiple objects can be mixed the object oriented way. When I start to think hard, I too have problems finding the right example. If a good (realistic) example has been found, then the next question is: would the less experianced coder understand?
Vladimir Bosnjak 22:49, 23 November 2006 (UTC)
Objects can be mixed the object oriented way very easily: just add pointers and methods (for an example see http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.5). Actually the so-called bridge pattern is one case of triviality and basic principles' violation that any newbie will start overexploiting the second month working as a C++ developer. Vladimir, I think the shape example is completely wrong: it violates encapsulation and abstraction and seriously mutilates inheritance. Shape should (really) be pure virtual and Drawcircle(), DrawSquare() and the like should be protected methods in the respective Shape subclasses. And of course data like radius should be private to the relevant classes. What does a square need a radius for? And of course you should have a method to set the drawingAPI pointer, otherwise it makes no sense, it is a huge roundabout just to make a few simple calls and introduce a lot of bugs ;-). Such a system could only draw circles and squares, but if you wanna draw a line you must touch all three classes, while if done correctly you merely need to add a line class. I believe you probably had in mind more complex subclasses of shape, such as "car" for example, which might need a number of calls to basic drawing api's. But again Thomas' way is of course correct and consistent with the sanity of OOP: the desired device context would be fed to the shape instance at run-time, so that it can call the api's functions directly.Dpser 13:18, 10 January 2007 (UTC)
The both of you are right but I am weary of using a device context in code examples because many students never used a device context before they're taught some basic patterns. However, I'm violating encapsulation and abstraction but I'm not motivated to do my best anymore because some lone ranger deletes C++ code because he thinks Java should be the standard. See my talk page. It takes way too many steps before some kind of justice is done. I may work a few hours on this topic only to see the next day the C++ code has dissapeared here as well... But make no mistake, I agree with both Dpser and Thomas and the C++ code should be corrected (encapsualation and abstraction violations). Le Comte Valmont 20:43, 22 February 2007 (UTC)
Please read this Talk:Design pattern (computer science)# Extraneous Examples the guy wasn't ill intended. Your source code should be moved to wiki books, with a link here to wikibooks just like Singleton pattern --lexxdark (talk) 05:02, 28 May 2009 (UTC)
I think the shape example indicates the Strategy Pattern much more than the Bridge. The Bridge is a good way of encapsulating differences when there are two independent axes of variation. It prevents an explosion of subclasses. Neither the car nor the shape example really shows this. 04 September 2007 —Preceding unsigned comment added by 216.99.6.9 (talk) 20:36, 4 September 2007 (UTC)

why are their a bunch of different code examples?[edit]

that's just retarded. Give one or two languages and leave it be. —The preceding unsigned comment was added by 169.231.11.44 (talk) 06:04, 27 February 2007 (UTC).

  • You might be taken seriously if you gave a reason why there should not be examples in many languages. 35.9.26.55 04:35, 1 March 2007 (UTC)
  • There are two problems with the examples. One is that there are two few of them. Why not C++? Why not Python? Why not Java? The other problem is exactly the opposite; there are too many of them. When you try to cover all bases, you end up with the main point of the article getting lost in the noise. I'm with the anonymous post above; just pick one or two representitive languages and let it go at that. Pick langages which are well known and/or easy to read without knowing the syntax details. -- RoySmith (talk) 14:10, 25 March 2007 (UTC)
  • I think it's a good thing that there are a few different languages here. After all, this is a software engineering page. There's a diagram, some explanatory text and a few examples. Sounds perfectly good to me. Philomathoholic 08:50, 1 September 2007 (UTC)
  • I think the purpose of this article is to give explanation about the pattern. So, a single example may be sufficient to describe the purpose of it. If there is too much examples, the readers may get lost. For example, there is a reference in the beginning of the article about Visual Prolog, so the reader will need to read the Visual Prolog even if it has already read the Java example. Maybe only one example may be sufficient (with clean and easy syntax language). The other examples could be given in the external links. There is a lot of references out there. Edans 16:16, 1 September 2007 (UTC)

I don't think the sample adequately defines the bridge pattern, it feel more like a Strategy pattern (Anon) —Preceding unsigned comment added by 98.111.71.111 (talk) 04:44, 4 March 2009 (UTC)

  • I am with adding as much as there could be. just add "examine only one example for deep understanding, by the language of your choice.". —Preceding unsigned comment added by 132.72.41.145 (talk) 11:24, 10 May 2009 (UTC)

I think it is good to provide example in different languages, because understanding of structure or pattern depends on your understanding of implemented language, we can always refer to example in language that we are familiar with, and of course we don’t have to look at all different language example, i.e. I am more comfortable with JAVA so I usually jump to java example, which give me enough understanding of pattern, i don’t have to look at python example if i don’t know python. —Preceding unsigned comment added by Shaikh sharique (talkcontribs) 08:31, 12 May 2010 (UTC)

Deleted many examples[edit]

I deleted many of the examples. Erlang isn't that popular (yet)(according to wikipedia), and c#, c++, and java are industry standards and university standards. —Preceding unsigned comment added by Michael miceli (talkcontribs) 06:08, 6 April 2008 (UTC)

Commentary:

"c# and java are industry standards and university standards" which means that they are the most important. What you did is wrong (at least in this respect). —Preceding unsigned comment added by 195.72.132.1 (talk) 12:27, 5 May 2008 (UTC)

I vote to leave only a Java example in place. C# programmers can easily understand the syntax (I'm a C# programmers by the way - not a Java one). This isn't a programming tutorial - so too much emphasis on implementation distracts from the point and clutters the article. LivingAndLearning (talk) 13:16, 8 October 2008 (UTC)

The c++ example has many problems. It has straight forward bugs (leaks) and some very controvertial coding habits (using namespace std;), but it's not all, the whole design doesn't fit c++. Seems to have been written by a programmer of a GC language with no c++ experience. I cannot fix it because I don't exactly understand the purpose of this pettern, but it is clearly not supposed to be done this way. --Itaj Sherman (talk) 12:44, 24 February 2009 (UTC)

Typo?[edit]

The bridge pattern is useful when not only the class itself varies often, but the class does also

Is there a typo in there? It effectively says 'when not only X but also X'! —Preceding unsigned comment added by 80.169.133.251 (talk) 10:47, 20 February 2009 (UTC)

I think there is a small mistake[edit]

I am not familiar with java that well- so maybe it's not a mistake, but: it is written:

  interface Shape {
     public void draw();                                            // low-level
     public void resizeByPercentage(double pct);     // high-level
  }
  class CircleShape implements Shape {
     private double x, y, radius;
     private DrawingAPI drawingAPI;
  }

but the "private DrawingApi drawingAPI" should be a member of the Shape interface. that's exactly the association (aggregation) from the Abstraction and the Implementor. or in other words, the implementor is a member of the abstraction, not of the refined abstractions. so it should be:

  interface Shape {
     public void draw();                                            // low-level
     public void resizeByPercentage(double pct);     // high-level
     private DrawingAPI drawingAPI;   //NEW LINE!!
  }

This is my first time i write something in Wikipedia. always was a reader. i hope i did it right :-) Nirhur (talk) 18:00, 20 May 2009 (UTC)

It's probably better the way it is because some other oo languages do not allow private/protected on interfaces (c#, I guess others too), I was actualy surprised that java allowed them, since interfaces should explain what an object exposes to other classes, not how it works internally
as it is put here "Interface generally refers to an abstraction that an entity provides of itself to the outside."
more intresting is that I couldn't find any example of interface definition like the above with public/private members. Did anyone check if it actually compiles? I looked around here http://java.sun.com/docs/books/tutorial/java/concepts/interface.html
--lexxdark (talk) 19:38, 27 May 2009 (UTC)
Another thing, private is not right in an interface (no way to use it) it should probably be protected
Further analyzing the documentation I noticed that it states that public can be omitted... But it does not say what can be used there, tho logically private can not be used
--lexxdark (talk) 19:56, 27 May 2009 (UTC)

Smok x (talk) 21:02, 13 July 2010 (UTC) Current Java example is not quite correct. One of the benefits of Bridge pattern is that clients do not need to know the exact implementation class. In the example the client explicitly instantiates DrawingAPI1 or DrawingAPI2. Shape should be abstract class instead of interface, and Shape must choose which implementation to use:

  public abstract class Shape {
     Shape() {
         // Choose implementation here. Clients don't know anything about it.
         drawingAPI = DrawingAPIFactory.getInstance().getDrawingAPI();
     }
     public abstract void draw();
     public abstract void resizeByPercentage(double pct);
     protected DrawingAPI getDrawingAPI();   // For subclasses.
     private DrawingAPI drawingAPI;
  }

No need for two Perl examples[edit]

I don't think there is a need for two Perl Moose examples so I moved this one to the discussion page. If there is more than one Perl example then one should probably use just core modules. Argel1200 (talk) 19:19, 12 August 2009 (UTC)

Perl (with Moose)[edit]

# Implementor
package Drawing::API;
use Moose::Role;
requires 'draw_circle';

# Concrete Implementor 1
package Drawing::API::1;
use Moose;
with 'Drawing::API';

sub draw_circle {
    my $self = shift;
    printf "API1.circle at %f:%f radius %f\n" => @_;
}

# Concrete Implementor 2
package Drawing::API::2;
use Moose;
with 'Drawing::API';

sub draw_circle {
    my $self = shift;
    printf "API2.circle at %f:%f radius %f\n" => @_;
}

# Abstraction
package Shape;
use Moose::Role;
requires qw( draw resize );

# Refined Abstraction
package Shape::Circle;
use Moose;
with 'Shape';

has $_  => ( is => 'rw', isa  => 'Any' ) for qw( x y r );
has api => ( is => 'ro', does => 'Drawing::API' );

sub draw {
    my $self = shift;
    $self->api->draw_circle( $self->x, $self->y, $self->r );
}

sub resize {
    my ($self, $percentage) = @_;
    $self->{r} *= $percentage;
}

# Client
package main;

my @shapes = (
    Shape::Circle->new( x=>1, y=>2, r=>3,  api => Drawing::API::1->new ),
    Shape::Circle->new( x=>5, y=>7, r=>11, api => Drawing::API::2->new ),
);

$_->resize( 2.5 ) and $_->draw for @shapes;

C++ example code doesn't match description[edit]

I don't know if all the code examples are the same, but the C++ example code doesn't match the description. The "maintains reference to the implementation" is in the wrong class, so it does not follow the pattern.
Długosz (talk) 16:12, 9 March 2010 (UTC)

Is it me or is this page wrong?[edit]

As some others have indicated, this seems to be describing the Strategy pattern, not the Bridge pattern. With the Strategy pattern you have a class with some functionality that needs to get implemented. The functionality is farmed off to a separate class who implements the functionality. With a Bridge pattern, you have an interface that must be implemented. You have multiple classes that implement that interface and you choose the correct one for your circumstances. It is often (almost always?) used in conjunction with an abstract factory.

The difference is subtle. The Strategy patten implements functionality that is plugged into an object. It is often a single method, or a group of methods that are used by the original object. For example, I might have a print method that prints to a screen and a print method that prints to a printer. The Bridge pattern implements an entire interface. So for instace if I am implementing a GUI I'll have a Swing version of my object and an Android version of my object. The bridge connects the abstraction to the implementation.

Mikekchar (talk) 02:27, 7 June 2012 (UTC)

It's disappointing to see that this page is still wrong after all these years, especially considering this is the first Google hit. As has been mentioned, *the example is not the bridge pattern*. More specifically, to quote directly from the GoF book, "All operations on...subclasses are implemented in terms of abstract operations from the...interface". Or in other words, the refined abstractions (CircleShape) should all just be calling methods of their abstract parent (Shape), which would presumably call drawingAPI methods. That's a bridge. This example is not.
206.53.78.59 (talk) 22:09, 2 January 2014 (UTC)
I don't think the above objections hold up. Note that it is the reasoning behind the pattern that defines its key elements, and that the details, the exact form, can vary. The full quote from the GoF book is "All operations on Window subclasses are implemented in terms of abstract operations from the WindowImp interface." That is, in their description (and this can be seen in other examples in the book), the Abstraction provides a way for RefinedAbstractions to obtain a reference to the current instance of Implementation, and then use the Implementation's interface to call operations on ConcreteImplementations. Furthermore, I don't think that it is crucial to the Bridge pattern that the reference to the Implementation resides in the Abstraction. Now, it's true that the "logistics" of supplying RefinedAbstractions with this dependency may be somewhat more complicated, but this doesn't imply that client code would suddenly become dependent on concrete implementations - the job of providing the dependency can still be delegated to another object, in much the same way as before (using a factory, or a DI container).
About the Strategy pattern: The form of Bridge and Strategy is nearly the same, and the difference is subtle. Bridge is a structural pattern that aims to decouple the Abstraction from its Implementations (and hide the concrete implementations from client code). Strategy, on the other hand, is a behavioral pattern, where concrete strategies define a family of related behaviors that client code can choose from - to quote the GoF book again, "Clients must be aware of different Strategies. [...] Therefore you should use the Strategy pattern only when the variation in behavior is relevant to clients." (Note that these behaviors are also implementations in the similar sense used in the description of the Bridge pattern - so the difference is really in the intent).
SlightlyStrangeQuark (talk) 23:39, 9 June 2016 (UTC)