简体   繁体   中英

What design pattern best fits this multiple implementations per customer method?

I have customers and each customer has a method to generate a reference number, but the reference number is different for each customer. I have an implementation below, but I am curious if there are any scalability issues and what design pattern is this or what design pattern would best fit this scenario:

//All customers will implement this.
public interface ICustomer
{

}

//All customers will implement this.
public interface IReferenceNumber
{
    string GenerateReferenceNumber();
}

   public class CustomerOne : ICustomer, IReferenceNumber
{
    public string GenerateReferenceNumber()
    {
        return "Reference Implemenation 1";
    }
}

public class CustomerTwo : ICustomer, IReferenceNumber
{
    public string GenerateReferenceNumber()
    {
        return "Reference Implemenation 2";
    }
} 

Here is how I might call it:

Dictionary<string,ICustomer> customers = new Dictionary<string,ICustomer>();

customers.Add("CustomerOne",new CustomerOne());
customers.Add("CustomerTwo",new CustomerTwo());

CustomerOne customerOne = (CustomerOne)customers["CustomerOne"];
CustomerTwo customerTwo = (CustomerTwo)customers["CustomerTwo"];

Console.WriteLine(customerOne.GenerateReferenceNumber());
Console.WriteLine(customerTwo.GenerateReferenceNumber());

Here are some more specific questions:

  1. The only reason why I had ICustomer was so I didn't have to do something like Dictionary<string,object> customers = new Dictionary<string,object>() , but now I am wondering if the IReferenceNumber is unnecessary and GenerateReferenceNumber should be moved into ICustomer

Also, I hate having to do CustomerOne customerOne = (CustomerOne)customers["CustomerOne"]; . Is there a way I can just get the Customer back and call the method on it without having to explicitly cast?

It seems based on comments, I should just have something like:

public class Customer
{
   public string GenerateReferenceNumber()
   {
       //Logic
       return "Default reference number";
   }
}

But if each customer requires unique logic to generate a reference number, how can I only keep one Customer object and override the behavior unless I have multiple GenerateReferenceNumber methods or one huge if else statement or different concrete implementations of customers that can use the default reference number or their own unique logic to generate one.

You can move the GenerateReferenceNumber() method to ICustomer interface and use it in dictionary much simpler:

//All customers will implement this.
public interface ICustomer
{
    string GenerateReferenceNumber();
}

public class CustomerOne : ICustomer
{
    public string GenerateReferenceNumber()
    {
        return "Reference Implemenation 1";
    }
}

public class CustomerTwo : ICustomer
{
    public string GenerateReferenceNumber()
    {
        return "Reference Implemenation 2";
    }
} 


Dictionary<string,ICustomer> customers = new Dictionary<string,ICustomer>();

customers.Add("CustomerOne",new CustomerOne());
customers.Add("CustomerTwo",new CustomerTwo());

var customerOne = customers["CustomerOne"];
var customerTwo = customers["CustomerTwo"];

Console.WriteLine(customerOne.GenerateReferenceNumber());
Console.WriteLine(customerTwo.GenerateReferenceNumber());

Or if you really want to keep both interfaces you can make the ICustomer derived from IReferenceNumber:

public interface ICustomer : IReferenceNUmber
{

}

and then the usage is the same - no cast required.

As for design pattern question, I don't see any specific design pattern that should be used here. It is basic case of inheritance, not the more complex behavior which has design pattern to implement it as a general approach. So no need for complicating this code with design patterns.

Using Composition over inheritance , I'd come up with something like this:

public class Customer
{
    private readonly IReferenceNumberGetter ReferenceNumberGetter;

    public Customer(IReferenceNumberGetter referenceNumberGetter)
    {
        ReferenceNumberGetter = referenceNumberGetter;
    }

    public string GenerateReferenceNumber()
    {
        return ReferenceNumberGetter.GenerateReferenceNumber();
    }

    // other Customer stuff
}

public interface IReferenceNumberGetter
{
    string GenerateReferenceNumber();
}

public class ReferenceNumberGetterOne : IReferenceNumberGetter
{
    public string GenerateReferenceNumber()
    {
        return "4";
    }
}

public class ReferenceNumberGetterTwo : IReferenceNumberGetter
{
    public string GenerateReferenceNumber()
    {
        return "42";
    }
}

And use it like this:

var customerOne = new Customer(new ReferenceNumberGetterOne()); 
var customerTwo = new Customer(new ReferenceNumberGetterTwo()); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM