CSharp example of Bridge design pattern

Jan 30, 2013 00:00 · 845 words · 4 minute read Programming Design pattern

What is Bridge pattern?

It help us to decouple interface from its implementation therefor they can be vary independently by adding one more higher layer abstraction to our interface and inject it to our concrete class.

Therefore our concrete class can use the new higher level of abstraction through our current interface without implementing it .

What we have

We have ErrorHandler class that accept exceptions and email it to appropriate persons to chase them.

error handler

public class ErrorHandler {
        private readonly Exception _errorMessage;
        public ErrorHandler(Exception errorMessage) {
            _errorMessage = errorMessage;
        } 

        public void Handle() {
          List<Sender> exceptionList=new List<Sender>();
            if(_errorMessage.InnerException==null) {
                var nullException=new NullException();
                nullException.Message = _errorMessage.Message;
                nullException.Source = _errorMessage.Source;
                nullException.ToAddress = "null@inadram.com";
                exceptionList.Add(nullException);
            }
            else {
                SimpleExpection simpleExpection=new SimpleExpection();
                simpleExpection.Message = _errorMessage.Message;
                simpleExpection.Source = _errorMessage.Source;
                simpleExpection.ToAddress = "simple@inadram.com";
                exceptionList.Add(simpleExpection);
            }

            foreach (var exp in exceptionList) {
                exp.Send();
            }

         }
}

Basically we have two types of exceptions, i.e. Simple exceptions and null exceptions.

exception

public class SimpleExpection:ISender {
        public string Message { get; set; }
        public string Source { get; set; }
        public string ToAddress { get; set; }
        readonly EmailException _emailException=new EmailException();

        public void Send() {
            _emailException.SendException(ToAddress, Message, Source);
        }
}

Both of them implementing from ISender interface and have Send method . the only difference is they send it to different persons.

Implenet from interface

public class NullException:ISender  {
        public string Message{get; set; }
        public string Source{get; set; }
        public string ToAddress { get; set; }  
        readonly EmailException _emailException = new EmailException();

        public void Send() {
            _emailException.SendException(ToAddress, Message, Source);
        }
}

Currently they only email the error message to the operators.

New requirement

We need to send the error message as Sms and also save it in an error log as well.

In this case we have two choices :

We can add this functionality to the interface and implement them in our concreate classes which bring us too many dependecies. Use bridge pattern to decouple the new functionalities from the concrete class by new interface Bridge pattern Make interface Abstract Now we have to abstract our interface and ask our concrete class to use it through ISender interface.

In this case, we change the ISender to an abstract class and change its name to Sender, then implement its constructor to use our new ISendAs interface.

There are two reasons to do that :

  • We want to make sure the Sender has the interface attribute . I.e. our concrete exception classes should always have the Send () method.
  • Ask its constructor to initialize our new interface instance to use in the concrete classes.

abstract

public abstract class Sender {
        private readonly ISendAs _sendAs;
         protected Sender(ISendAs sendAs) {
            _sendAs = sendAs;
        }     

        public abstract  void Send();
}

Define new Interface

Our new interface will have the new functionalities signature.

new interface

public interface ISendAs {
	void Send(string message, string source, EmailException emailException);
}

Update concrete class to use new interface.

Inject the new interface to the constructor of our concrete classes through the abstract class . Therefore we can call our new interface functionalities through our abstract class.

implemention

public class NullException : Sender    {
        public NullException(ISendAs sendAs) : base(sendAs) { } 

        public string Message { get; set; }
        public string Source { get; set; }
        public string ToAddress { get; set; }
        private readonly EmailException _emailException = new EmailException();
        
        public override void Send() {
            SendAs.Send(ToAddress, Message, Source, _emailException);
        }
}

Add Send Types

The new send types need to implement from our new interface.

Add send type classes

public class EmailException:ISendAs {
        public string Status = string.Empty;
        public void Send(string toAddress, string message, string source, EmailException emailException) {
            //TODO :send it as email
           Status = "send successfully as email";
        }
}

public class SmsException : ISendAs {
    public string Status = string.Empty;
    public void Send(string toAddress, string message, string source, EmailException emailException) {
        //TODO :send it as sms
        Status = "send successfully as sms";
    }
}

public class LogException : ISendAs {
      public string Status = string.Empty;
      public void Send(string toAddress, string message, string source, EmailException emailException) {
          //TODO :send it as log
          Status = "send successfully as log";
      }
}    

Ask errorHandler to use desire error type

error handler

public class ErrorHandler {
       private readonly Exception _errorMessage;
       public List<string> sendStatus = new List<string>();
       public ErrorHandler(Exception errorMessage) {
        _errorMessage = errorMessage;
       }

        public void Handle() {
          List<Sender> exceptionList=new List<Sender>();       
            if(_errorMessage.InnerException==null) {
                var emailnullException=new NullException(new EmailException());
                AddToListNullException(emailnullException, exceptionList, "null@inadram.com");
                 var smsnullException = new NullException(new SmsException());
                AddToListNullException(smsnullException, exceptionList, "07771216871");
                 var lognullException = new NullException(new LogException());
                AddToListNullException(lognullException, exceptionList, "nulllog.txt");
            } else {
                var emailsimpleException = new SimpleExpection(new EmailException());
                AddToListSimpleException(emailsimpleException, exceptionList, "simple@inadram.com");
                 var smsSimpleException = new SimpleExpection(new SmsException());
                AddToListSimpleException(smsSimpleException, exceptionList, "07771216872");
                 var lognsimpleException = new SimpleExpection(new LogException());
                AddToListSimpleException(lognsimpleException, exceptionList, "simplelog.txt");             
            }

            foreach (var exp in exceptionList) {
                 sendStatus.Add(exp.Send());
            }
        }

         private void AddToListNullException(NullException emailnullException, List<Sender> exceptionList,string toAddress) {
            emailnullException.Message = _errorMessage.Message;
            emailnullException.Source = _errorMessage.Source;
            emailnullException.ToAddress = toAddress;
            exceptionList.Add(emailnullException);
        }

         private void AddToListSimpleException(SimpleExpection emailSimpleException, List<Sender> exceptionList, string toAddress) {
            emailSimpleException.Message = _errorMessage.Message;
            emailSimpleException.Source = _errorMessage.Source;
            emailSimpleException.ToAddress = toAddress;
            exceptionList.Add(emailSimpleException);
        }
}

Download

Feel free to download the full source code of this example from my GitHub