1

I saw a code example online that uses adapter pattern as: enter image description here enter image description here enter image description here

if you look at the HR system, the employee information in the form of string array and the ProcessSalary method of the Third Party Billing System wants to data in List. So, the HR System cannot call directly to the Third Party Billing System because List and string array are not compatible. So we use adapter pattern, the full code is:

namespace AdapterDesignPattern
{
    public interface ITarget
    {
        void ProcessCompanySalary(string[,] employeesArray);
    }
}



namespace AdapterDesignPattern
{
    public class EmployeeAdapter : ThirdPartyBillingSystem, ITarget
    {
        public void ProcessCompanySalary(string[,] employeesArray)
        {
            string Id = null;
            string Name = null;
            string Designation = null;
            string Salary = null;

            List<Employee> listEmployee = new List<Employee>();

            for (int i = 0; i < employeesArray.GetLength(0); i++)
            {
                for (int j = 0; j < employeesArray.GetLength(1); j++)
                {
                    if (j == 0)
                    {
                        Id = employeesArray[i, j];
                    }
                    else if (j == 1)
                    {
                        Name = employeesArray[i, j];
                    }
                    else if (j == 1)
                    {
                        Designation = employeesArray[i, j];
                    }
                    else
                    {
                        Salary = employeesArray[i, j];
                    }
                }

                listEmployee.Add(new Employee(Convert.ToInt32(Id), Name, Designation, Convert.ToDecimal(Salary)));
            }

            Console.WriteLine("Adapter converted Array of Employee to List of Employee");
            Console.WriteLine("Then delegate to the ThirdPartyBillingSystem for processing the employee salary\n");
            ProcessSalary(listEmployee);
        }
    }
}

// Cilent
namespace AdapterDesignPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            string[,] employeesArray = new string[5, 4] 
            {
                {"101","John","SE","10000"},
                {"102","Smith","SE","20000"},
                {"103","Dev","SSE","30000"},
                {"104","Pam","SE","40000"},
                {"105","Sara","SSE","50000"}
            };
            
            ITarget target = new EmployeeAdapter();  <-------why not just use new EmployeeAdapter() directly?
            Console.WriteLine("HR system passes employee string array to Adapter\n");
            target.ProcessCompanySalary(employeesArray); 
        }
    }
}

I just don't understand one thing, is ITarget interface really necessary? Why not just get rid of it, then the client can do this:

namespace AdapterDesignPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            string[,] employeesArray = new string[5, 4] { ... };
            Console.WriteLine("HR system passes employee string array to Adapter\n");
            new EmployeeAdapter().ProcessCompanySalary(employeesArray);
        }
    }
}

so that we can call ProcessCompanySalary on EmployeeAdapter instance directly?

8
  • Presumably the ITarget interface is there so that you can change out the implementation, if needed. Apr 28 '21 at 15:46
  • @RobertHarvey then I just change the code of EmployeeAdapter directly
    – slowjams
    Apr 28 '21 at 15:47
  • Yes, but you can't do that at runtime. Apr 28 '21 at 15:48
  • Usually, I see Interfaces in use for one of three reasons: 1. To allow a test harness to substitute its own mock implementation, 2. To allow the program to choose a suitable implementation at runtime (i.e. with a factory), and 3. To allow the implementation of polymorphic capabilities, like ICloneable and IEnumerable. Apr 28 '21 at 15:50
  • 1
    In this particular case (the Adapter Pattern), it would be quite inconvenient to have to re-wire your Adapter in code every time there needs to be a change. The whole point of the Adapter is to decouple the implementation from the thing being adapted; if you forced your consumers to write new code each time, you might as well just wire that code up directly, instead of using an Adapter. Apr 28 '21 at 15:57
1

Your picture shows it: assume the HR system to be an existing system, something which cannot easily be touched by you, a component which shall not have any direct dependency to the "third party billing system". The same is obviously true the other way round: the billing system does not know anything about the HR system.

Since the EmployeeAdapter obviously has a dependency to the billing system, it cannot be part of the HR system. But let us assume the designers of the HR systems have foreseen the situation and provided an interface ITarget there, to allow the injection of an arbitrary component for processing salaries.

So your Main program will live in a component under your own control, which references both the HRSystem and the ThirdPartyBilling, hence the situation could be scetched like this:


class Program
{
    static void Main(string[] args)
    {
        // ITarget is an existing interface from HRSystem
        ITarget target = new EmployeeAdapter();

        // the HR system will probably look a lot different
        // in reality, but there will be instances coming
        // from there, maybe "injected" or setup somewhere else
        string[,] employeesArray = new string[5, 4] { ... };
        HRSystem hrSystem= new HRSystem(target, employeesArray);
        
        // will internally call ProcessCompanySalary
        hrSystem.StartProcessing(); 
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.