Spring 5 Design Patterns
上QQ阅读APP看书,第一时间看更新

Sample implementation of the Bridge design pattern

Let's look at the following example, where we will demonstrate the use of the Bridge design pattern. Suppose you want to open two types of accounts, one is a Savings Account and the other is a Current Account in the banking system.

System without using the Bridge design pattern

Let's look at an example without using the Bridge design pattern. In the following figure, you can see the relationship between the Bank and Account interfaces:

System without using the Bridge design pattern

Let's create a design without using the Bridge design pattern. First create an interface or an abstract class, Bank. And then create its derived classes: IciciBank and HdfcBank. To open an account in the bank, first decide on the types of account classes--Saving Account and Current Account, these classes extend the specific banks classes (HdfcBank and IciciBank). There is a simple deep inheritance hierarchy in this application. So what is wrong with this design as compared to the preceding figure? You will notice that in this design, there are two parts, one is the abstraction part and the other is the implementation part. Client code interacts with the abstraction part. Client code can only access new changes or new functionalities of the implementation part when you will update the abstraction part, meaning the parts, the abstraction, and the implementation, are tightly coupled with each other.

Now let's see how to improve this example using the Bridge design pattern:

System with the Bridge design pattern

In the following figure, we create a relation between the Bank and Account interface by using the Bridge design pattern:

System using Bridge Design Pattern

UML structure for the Bridge design pattern

Let's look at the following figure of how the Bridge design pattern solves these design issues, as seen in the example where we did not use the Bridge design pattern. Bridge pattern separates the abstraction and implementation into two class hierarchies:

UML for Bridge design pattern

We have an Account interface that is acting as a bridge implementer and the concrete classes SavingAccount, and CurrentAccount implementing the Account interface. The Bank is an abstract class and it will use object of Account.

Let's create a bridge implementer interface.

Following is the Account.java file:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public interface Account { 
      Account openAccount(); 
      void accountType(); 
    } 

Create concrete bridge implementer classes to implement the implementer interface. Let's create a SavingAccount class as an implementation of Account.

Following is the SavingAccount.java file:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public class SavingAccount implements Account { 
      @Override 
      public Account openAccount() { 
         System.out.println("OPENED: SAVING ACCOUNT "); 
         return new SavingAccount(); 
      } 
      @Override 
      public void accountType() { 
        System.out.println("##It is a SAVING Account##"); 
      } 
    } 

Create a CurrentAccount class that implements the Account interface.

Following is the CurrentAccount.java file:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public class CurrentAccount implements Account { 
      @Override 
      public Account openAccount() { 
        System.out.println("OPENED: CURRENT ACCOUNT "); 
        return new CurrentAccount(); 
      } 
      @Override 
      public void accountType() { 
        System.out.println("##It is a CURRENT Account##"); 
      } 
    } 

Create abstraction in the Bridge design pattern, but first, create the interface Bank.

Following is the Bank.java file:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public abstract class Bank { 
      //Composition with implementor 
      protected Account account; 
      public Bank(Account account){ 
         this.account = account; 
      } 
      abstract Account openAccount(); 
    } 

Let's implement the first abstraction for the Bank interface and see the following implementation class for the Bank interface.

Following is the IciciBank.java file:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public class IciciBank extends Bank { 
      public IciciBank(Account account) { 
        super(account); 
      } 
      @Override 
      Account openAccount() { 
        System.out.print("Open your account with ICICI Bank"); 
        return account; 
      } 
    } 

Let's implement the second abstraction for the Bank interface and look at the following implementation class for the Bank interface.

Following is the HdfcBank.java file:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
      public class HdfcBank extends Bank { 
        public HdfcBank(Account account) { 
          super(account); 
        } 
        @Override 
        Account openAccount() { 
          System.out.print("Open your account with HDFC Bank"); 
          return account; 
        } 
      } 

Create a demonstration class of the Bridge design pattern.

Following is the BridgePatternMain.java file:

    package com.packt.patterninspring.chapter3.bridge.pattern; 
    public class BridgePatternMain { 
      public static void main(String[] args) { 
         Bank icici = new IciciBank(new CurrentAccount()); 
         Account current = icici.openAccount(); 
         current.accountType(); 
         Bank hdfc = new HdfcBank(new SavingAccount()); 
         Account saving = hdfc.openAccount(); 
         saving.accountType(); 
      } 
    } 

Let's run this demo class and see the following output in the console:

Now that we've seen the Bridge design pattern, let's turn to a different variant of it--the composite design pattern.