1

I have two products, Product A and Product B. Product A has a list of Campaigns created using M database calls and Product B also has a list of campaigns created by separate N database calls.

Important Point to be noted - Some calls are common between M and N.

Now for Product A we call the list of M Database calls and combine them into a single list and vice versa for Product B.

Now we want to apply a list of X Filters on Product A and a list of Y Filters on Product B in order to get filtered list of Product A campaigns or Product B campaigns depending on the client's call for a particular Product.

What do you suggest, how should we approach it for the design of the system? Any suggestions or link or reference to guide me in the right direction would be greatly appreciated.

Sanjay Soni
  • 201
  • 1
  • 13
  • Do you want to merge the list of Campaigns from both Products and then apply filters to that single list based on which Product each is related with? That is it? – João Dias Sep 10 '21 at 11:16
  • Made changes to the descriptions, I want to apply filters to Product A campaigns only and would return final result as Product A Campaign List. – Sanjay Soni Sep 10 '21 at 12:01

2 Answers2

1

Can we Use Factory Method here? we can decide the Product which we want to create on runtime and also the filters which we want to apply to the product on runtime. this way if we want to add new products or new filters we can easily add them without making changes to the existing products or filter

https://refactoring.guru/design-patterns/factory-method

  • factory definitely comes into the picture whenever you have multiple same family products, in detail if you see there is a filter factory, and those list of filters can be managed via chain of responsibility principles. Collecting product list from different sources also comes into template design pattern category. – Sanjay Soni Sep 22 '21 at 04:13
0

I think composition is the key word here. You could have a CampaignsProvider interface that's implemented by multiple 'sources' like API1CampaignsProvider, API2CampaignsProvider, InMemoryCacheCampaignsProvider, etc.

interface CampaignsProvider {
  func campaignsForProduct(product: Product) -> [Campaign]
}

Then you could have a class that composes all the providers like so:

class CampaignsProviderComposer: CampaignsProvider {
   let providers: [CampaignsProvider]
   init(providers: [CampaignsProvider]) {
      self.providers = providers
   }

   func campaignsForProduct(_ product: Product) -> [Campaign] {
       var allCampaings: [Campaign] = []
       providers.forEach { p in
           allCampaigns.appendAll(p.campaignsForProduct(product))
       }
   }
}

Then just compose with all different sources

var productA = Product(name: "A")
let campaignsProviderA = CampaignsProviderComposer(providers: [
   Api1CampaignsProvider(),
   Api2CampaignsProvider()
])
productA.campaigns = campaignsProvider.campaignsForProduct(productA)

var productB = Product(name: "B")
let campaignsProviderB = CampaignsProviderComposer(providers: [
   Api3CampaignsProvider(),
   Api4CampaignsProvider()
])
productB.campaigns = campaignsProvider.campaignsForProduct(productB)

As for filtering, a similar approach could be taken, having a CampaignsFilter interface, and have different implementations with different dependencies for different products