Categories: Design Pattern

Structural Patterns – Bridge

Bridge – Separates an object’s interface from its implementation – abstraction layer and implementation layer, which can be developed independently of each other.

From Design Patterns – Structural Patterns

Structure

Bridge pattern – Class diagram UML

Applicability

The program has divided and organizes the classes. These classes have several function variants. For example, the class can work in several individual databases.

The solution project has extended classes in several orthogonal dimensions.

When the solution project is running, the developers want the project to switch implementations; using the bridge will be a better choice.

Pros and Cons

PRONS

  • Create platform-independent classes and apps.
  • Client-side code works with high-level abstraction.
  • Open-closed principle.
  • Single Responsibility Principle.

CONS

  • Maybe the code becomes the complexity by applying this pattern to a cohesive high-level class.

How to Implement

#1 Basic Sample

class Program
{
 static void Main(string[] args)
 {
  Abstraction _abstraction;

  _abstraction = new Abstraction(new ImplementationA());
  Console.WriteLine(_abstraction.Operation());
  _abstraction = new Abstraction(new ImplementationB());
  Console.WriteLine(_abstraction.Operation());

  ExtendAbstraction2 extendAbstraction2 = new ExtendAbstraction2(new ImplementationA());
  extendAbstraction2.Commit = "Commit result";

  Console.WriteLine(extendAbstraction2.Operation());

  Console.ReadKey();
 }
}

public interface IImplementation
{
 string OperationImplementation();
}

class ImplementationA : IImplementation
{
 public string OperationImplementation() => "ImplementationA: The result in platform A.\n";
}

class ImplementationB : IImplementation
{
 public string OperationImplementation() => "ImplementationA: The result in platform B.\n";
}

class Abstraction
{
 protected IImplementation implementation;

 public Abstraction(IImplementation _implementation)
 {
  this.implementation = _implementation;
 }

 public virtual string Operation() => "Abstract: base operation with:\n" + implementation.OperationImplementation();
}

class ExtendAbstraction : Abstraction
{
 public ExtendAbstraction(IImplementation implementation) : base(implementation)
 { }

 public override string Operation()
 {
  return "ExtendedAbstraction: Extended operation with:\n" +
   base.implementation.OperationImplementation();
 }
}

class ExtendAbstraction2 : Abstraction
{
 public ExtendAbstraction2(IImplementation implementation) : base(implementation)
 { }

 public string Commit { get; set; } = string.Empty;

 public override string Operation()
 {
  StringBuilder Result = new StringBuilder();
  Result.Append( Commit + "\n");
  Result.Append("ExtendedAbstraction2: Extended operation with:\n" +
    base.implementation.OperationImplementation());
  return Result.ToString();
 }
}

#2 Web Application Project

Step 1 Create the generic repository mechanism without the generic type variable—one interface class file called “IBridge” under the Core project. Create two repository files under the Infra project. One repository class file name sets “BridgeRepoA.” Another repository class file name sets “BridgeRepoB.”

Fig 1 Interface&Repository solution explorer

Step 2 Create the entity model class variant.

public class Enterprise_MVC_Core_Variant
{
 public int ID { get; set; }

 public string Name { get; set; }

 public int? Age { get; set; }

 public string Commit { get; set; } = string.Empty;
}

Step 3 Create the GET method in the IBridge class file. Two repository class files inherit the IBridge class file—statement the IGenericTypeRepository interface class variable and the entity model class variant variable in these repository files.

public class BridgeRepoA : IBridge
{
 private IGenericTypeRepository<Enterprise_MVC_Core> repo;
 private IList<Enterprise_MVC_Core_Variant> variant;

 public BridgeRepoA(IGenericTypeRepository<Enterprise_MVC_Core> _repo)
 {
  this.repo = _repo;
 }

 public Task<object> GetAll()
 {
  dynamic temp = this.repo.GetAll().Result;

  if (temp != null || temp != "")
  {
   variant = new List<Enterprise_MVC_Core_Variant>();

   for (int i = 0; i < temp.Count; i++)
   {
    variant.Add(new Enterprise_MVC_Core_Variant()
    {
     ID = temp[i].ID,
     Name = temp[i].Name,
     Age = temp[i].Age,
     Commit = "From Bridge repository B."
    });
   }
  }
  return Task.Run(() => variant as object);
 }
}

Step 4 Create the abstract type class and the extend-abstract class under the Core project. The abstract type class file name sets “BridgeAbstraction.” Another class file name sets “ExtendBridgeAbstraction,” which inherits the BridgeAbstraction class file. Statement the IBridge variable in the BridgeAbstraction class file, then creating the new method called “GetAll.” The GetAll way calls the IBridge’s GetAll method.

public abstract class BridgeAbstraction
{
 protected IBridge bridge;

 public BridgeAbstraction(IBridge _bridge)
 {
  this.bridge = _bridge;
 }

 public virtual Task<object> GetAll()
 {
  return Task.Run(() => this.bridge.GetAll());
 }
}

Step 5 Create the overall method for the GetAll method in the ExtendBridgeAbstraction class file without statement the IBridge variable.

public class ExtendBridgeAbstraction : BridgeAbstraction
{
 public ExtendBridgeAbstraction(IBridge bridge) : base(bridge)
 { }

 public override Task<object> GetAll()
 {
  return base.GetAll();
 }
}

Step 6 Add the IBridge file and two repository files to the scoped service in the Startup.cs file, which is under the web project.

Fig 2 Startup.cs file under the web project

Step 7 Create the new controller file and the view file under the web project. New controller file name sets “BridgeController.” The view part only creates the Index page without other view page files.

Fig 3 BiridgeController file source code
Fig 4 Bridge pattern running result

Reference

davidsky69

View Comments

Recent Posts

API Gateway in .NET 5 with Ocelot

What is the API gateway? An API gateway is an API management tool that sits…

3 years ago

.NET 5 application with Onion architecture

The .NET 5 SDK is a kind of milestone in the .NET world. The .NET…

4 years ago

SOLID Principles – Dependency inversion principle

In object-oriented design, the dependency inversion principle is a specific methodology for loosely coupling software…

4 years ago

SOLID Principles – Interface segregation principle

In the field of software engineering, the interface segregation principle (ISP) states that no code…

4 years ago

SOLID Principles – Liskov substitution principle

Subtype Requirement: Let  be a property provable about objects  of type T. Then  should be true for objects  of type S where S is…

4 years ago

SOLID Principles – Open-closed principle

In object-oriented programming, the open–closed principle states "software entities (classes, modules, functions, etc.) should be…

4 years ago