Editing Combined Patterns New

Bridge


Objective

Separate an abstraction from its implementation, so that both may vary independently.

Function

Decouple an abstraction from its implementation.

Structure

The client class does not want to deal with platform-dependent details. The Bridge pattern encapsulates this complexity behind a 'wrap'. of abstraction.Bridge emphasizes the identification and decoupling of "interface" abstraction from "implementation" abstraction.

The structure that meets this pattern is shown in Figure 1

Responsive image

Figure 1: UML Diagram Bridge Pattern

Applications

  • You want to share an implementation among multiple objects, and that this fact is transparent to the client.

  • A permanent link between an abstraction and its implementation needs to be removed, for example, when an implementation needs to be linked or changed at run time.

  • The need to implement various representations of an abstraction can generate a proliferation of classes.

  • Abstraction and implementation must be extensible through aggregation of subclasses. In this case the bridge design pattern allows the combination of different abstractions and implementations and extend them independently.

  • Changes in the implementation of an abstraction should not impact the client classes, their code should not be recompiled.

Design Patterns Collaborators

  • The Abstract Factory pattern can create and set a certain bridge pattern.

Scope of action

Applied at the object level.

Problem

To make use of different representations of an abstract class, it is required to implement an inheritance since an abstract class defines the interface for such abstraction and the concrete, or inherited, classes implement the different ways, however this implementation is limiting, considering that permanently linked to abstraction, which makes it difficult to modify, extend, and reusing abstractions and implementations independently.

Solution

The bridge design pattern allows a bridge to connect a abstraction of its different implementations, which creates a hierarchy for the abstractions and another for the implementations, allowing to manage both class hierarchies independently.

Diagram or Implementation

Responsive image

Figure 2: UML Diagram Bridge Pattern

Figure 2 explains the behaviour of the bridge pattern by means of a sequence diagram.

  • Client class executes an AbstractionImplement operation.

  • The class AbstractionImplement replicates the request to ConcreteImplementor, in this step the class AbstractionImplement could perform a conversion of the parameters to execute the ConcreteImplementor.

  • ConcreteImplementor returns the results to the AbstractionImplement class.

  • Finally the AbstractionImplement class converts the results of the ConcreteImplementor to be returned to the client.


Study Cases


Drawing Editor System
Responsive image

Figure 3: UML Diagram Drawing Editor System


Responsive image

Figure 4: UML Diagram Drawing Editor System



Tourist Reservation System
Responsive image

Figure 5: UML Diagram Tourist Reservation System


Responsive image

Figure 6: UML Diagram Tourist Reservation System


Implementations of the bridge pattern:

    	
    		
"""
Decouple an abstraction from its implementation so that the two can vary
independently.
"""

import abc


class Abstraction:
    """
    Define the abstraction's interface.
    Maintain a reference to an object of type Implementor.
    """

    def __init__(self, imp):
        self._imp = imp

    def operation(self):
        self._imp.operation_imp()


class Implementor(metaclass=abc.ABCMeta):
    """
    Define the interface for implementation classes. This interface
    doesn't have to correspond exactly to Abstraction's interface; in
    fact the two interfaces can be quite different. Typically the
    Implementor interface provides only primitive operations, and
    Abstraction defines higher-level operations based on these
    primitives.
    """

    @abc.abstractmethod
    def operation_imp(self):
        pass


class ConcreteImplementorA(Implementor):
    """
    Implement the Implementor interface and define its concrete
    implementation.
    """

    def operation_imp(self):
        pass


class ConcreteImplementorB(Implementor):
    """
    Implement the Implementor interface and define its concrete
    implementation.
    """

    def operation_imp(self):
        pass


def main():
    concrete_implementor_a = ConcreteImplementorA()
    abstraction = Abstraction(concrete_implementor_a)
    abstraction.operation()


if __name__ == "__main__":
    main()    	
    	
    	
    		
abstract class BridgeBook {     
    private $bbAuthor;
    private $bbTitle;
    private $bbImp;
    function __construct($author_in, $title_in, $choice_in) {
      $this->bbAuthor = $author_in;
      $this->bbTitle  = $title_in;
      if ('STARS' == $choice_in) {
        $this->bbImp = new BridgeBookStarsImp();
      } else {
        $this->bbImp = new BridgeBookCapsImp();
      }
    }    
    function showAuthor() {
      return $this->bbImp->showAuthor($this->bbAuthor);
    }
    function showTitle() {
      return $this->bbImp->showTitle($this->bbTitle);
    }
}
 
class BridgeBookAuthorTitle extends BridgeBook {    
    function showAuthorTitle() {
      return $this->showAuthor() . "'s " . $this->showTitle();
    }
}  
 
class BridgeBookTitleAuthor extends BridgeBook {    
    function showTitleAuthor() {
      return $this->showTitle() . ' by ' . $this->showAuthor();
    }
}
 
abstract class BridgeBookImp {    
    abstract function showAuthor($author);
    abstract function showTitle($title);
}

class BridgeBookCapsImp extends BridgeBookImp {    
    function showAuthor($author_in) {
      return strtoupper($author_in); 
    }
    function showTitle($title_in) {
      return strtoupper($title_in); 
    }
}

class BridgeBookStarsImp extends BridgeBookImp {    
    function showAuthor($author_in) {
      return Str_replace(" ","*",$author_in); 
    }
    function showTitle($title_in) {
      return Str_replace(" ","*",$title_in); 
    }
}

  writeln('BEGIN TESTING BRIDGE PATTERN');
  writeln('');
 
  writeln('test 1 - author title with caps');
  $book = new BridgeBookAuthorTitle('Larry Truett','PHP for Cats','CAPS');
  writeln($book->showAuthorTitle());
  writeln('');

  writeln('test 2 - author title with stars');
  $book = new BridgeBookAuthorTitle('Larry Truett','PHP for Cats','STARS');
  writeln($book->showAuthorTitle());
  writeln('');

  writeln('test 3 - title author with caps');
  $book = new BridgeBookTitleAuthor('Larry Truett','PHP for Cats','CAPS');
  writeln($book->showTitleAuthor());
  writeln('');

  writeln('test 4 - title author with stars');
  $book = new BridgeBookTitleAuthor('Larry Truett','PHP for Cats','STARS');
  writeln($book->showTitleAuthor());
  writeln('');

  writeln('END TESTING BRIDGE PATTERN');

  function writeln($line_in) {
    echo $line_in."
"; }
    	
    		
class Node {
    public int value;
    public Node prev, next;

    public Node(int i) {
        value = i;
    }
}

class Stack {
    private StackImpl impl;

    public Stack( String s ) {
        if (s.equals("array")) {
            impl = new StackArray();
        } else if (s.equals("list")) {
            impl = new StackList();
        } else {
            System.out.println("Stack: unknown parameter");
        }
    }

    public Stack() {
        this("array");
    }

    public void push(int in) {
        impl.push( in );
    }

    public int pop() {
        return impl.pop();
    }

    public int top() {
        return impl.top();
    }

    public boolean isEmpty() {
        return impl.isEmpty();
    }

    public boolean isFull() {
        return impl.isFull();
    }
}

class StackHanoi extends Stack {
    private int totalRejected = 0;

    public StackHanoi() {
        super("array");
    }

    public StackHanoi(String s) {
        super(s);
    }

    public int reportRejected() {
        return totalRejected;
    }

    public void push(int in) {
        if (!isEmpty() && in > top()) {
            totalRejected++;
        }
        else {
            super.push(in);
        }
    }
}

class StackFIFO extends Stack {
    private StackImpl stackImpl = new StackList();

    public StackFIFO() {
        super("array");
    }

    public StackFIFO(String s) {
        super(s);
    }

    public int pop() {
        while (!isEmpty()) {
            stackImpl.push(super.pop());
        }
        int ret = stackImpl.pop();
        while (!stackImpl.isEmpty()) {
            push(stackImpl.pop());
        }
        return ret;
    }
}

interface StackImpl {
    void push(int i);
    int pop();
    int top();
    boolean isEmpty();
    boolean isFull();
}

class StackArray implements StackImpl {
    private int[] items;
    private int total = -1;

    public StackArray() {
        this.items = new int[12];
    }

    public StackArray(int cells) {
        this.items = new int[cells];
    }

    public void push(int i) {
        if (!isFull()) {
            items[++total] = i;
        }
    }

    public boolean isEmpty() {
        return total == -1;
    }

    public boolean isFull() {
        return total == items.length - 1;
    }

    public int top() {
        if (isEmpty()) {
            return -1;
        }
        return items[total];
    }

    public int pop() {
        if (isEmpty()) {
            return -1;
        }
        return items[total--];
    }
}

class StackList implements StackImpl {
    private Node last;

    public void push(int i) {
        if (last == null) {
            last = new Node(i);
        } else {
            last.next = new Node(i);
            last.next.prev = last;
            last = last.next;
        }
    }

    public boolean isEmpty() {
        return last == null;
    }

    public boolean isFull() {
        return false;
    }

    public int top() {
        if (isEmpty()) {
            return -1;
        }
        return last.value;
    }

    public int pop() {
        if (isEmpty()) {
            return -1;
        }
        int ret = last.value;
        last = last.prev;
        return ret;
    }
}

public class BridgeDisk {
    public static void main(String[] args) {
        Stack[] stacks = {new Stack("array"), new Stack("list"),
                new StackFIFO(), new StackHanoi()};
        for (int i=1, num; i < 15; i++) {
            for (int j=0; j < 3; j++) {
                stacks[j].push( i );
            }
        }
        Random rn = new Random();
        for (int i=1, num; i < 15; i++) {
            stacks[3].push(rn.nextInt(20));
        }
        for (int i=0, num; i < stacks.length; i++) {
            while (!stacks[i].isEmpty()) {
                System.out.print(stacks[i].pop() + "  ");
            }
            System.out.println();
        }
        System.out.println("total rejected is " + ((StackHanoi)stacks[3]).reportRejected());
    }
}