Skip to content

Bridge

Bridge is a pattern that allows you to separate abstractions that are related to each other by the inheritance mechanism. Suppose we implement a simple shop that sells coffee or tea. Each of these drinks can be purchased by inheriting the corresponding object representing the purchase. In this case, the implementation is closely related to the abstraction (e.g. the Coffee class together with theCoffeePurchase class, which could represent a purchase). It implies numerous changes in many classes if the concept changes. A better idea is to separate the abstraction from the implementation and group existing elements into separate class hierarchies.

The implementation of the above-described case, without using a Bridge, could look like this:

no_bridge

Using the bridge, we can divide these objects into two groups:

  • Coffee, Tea with the separation of the common interface Drink
  • CoffeePurchase, TeaPurchase with the separation of a common DrinkPurchase interface for this abstraction

Drink andDrinkPurchase interfaces are the (single) bridge between these abstraction hierarchies.

bridge

An implementation with a Bridge could look like this:

public enum Taste {
  BITTER, SWEET, CHOCOLATE, NUT, LEMON
}
public interface Drink {
  String getVolume();
  boolean isAddictive();
  int getNumberOfSugarLumps();
  Taste getTaste();
}
import static pl.sdacademy.bridge.Taste.BITTER;

public class Coffee implements Drink {

  @Override
  public String getVolume() {
    return "500ml";
  }

  @Override
  public boolean isAddictive() {
    return true;
  }

  @Override
  public int getNumberOfSugarLumps() {
    return 0;
  }

  @Override
  public Taste getTaste() {
    return BITTER;
  }
}
public class Tea implements Drink {
  @Override
  public String getVolume() {
    return "200ml";
  }

  @Override
  public boolean isAddictive() {
    return false;
  }

  @Override
  public int getNumberOfSugarLumps() {
    return 5;
  }

  @Override
  public Taste getTaste() {
    return Taste.SWEET;
  }
}
public interface DrinkPurchase {
  Drink buy(final Double cost);
}
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class CoffeePurchase implements DrinkPurchase {

  @Override
  public Drink buy(final Double cost) {
    log.info("Buying a a coffee for {}", cost);
    return new Coffee();
  }
}
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class TeaPurchase implements DrinkPurchase {

  @Override
  public Drink buy(final Double cost) {
    log.info("Buying a a tea for {}", cost);
    return new Tea();
  }
}