1

I am looking for the best pattern to apply in my problem. I have an interface that defines my service class functionality

interface NegotiationInterface {
    abstract public function resetNegotiation(Negotiation $negotiantion);
} 

A main class implements it

public class NegotiationService implements NegotiationInterface {

    public function __construct(…Some Dependencies…)
    {
    ….        
    }

    public function resetNegotiation(Negotiation $negotiantion){
    …. //All business logic
    }
}

NegotiationService is registered under DI container(Symfony based) and used all over application by its service id.

$negotiationService = $this->container->get(“negotiation_service”);
$negotiationService->resetNegotiation($negotiation);

However some of our clients(negotiation contains the client info), require an additional step after calling resetNegotiation, for example our common business logic + calling a webservice. I reached at decorator pattern but I am not sure if it would be the best approach while using DI. If so how would I apply together with DI. I would like to have those extra steps loaded dynamically according to client.

1
  • At this point, there are two good answers to your question. Please take a look at them and accept one if the answers that helped you. Alternately, do comment on the answers for further clarification. That said, I have provided an example with the composite pattern which I believe should work very well in your case.. Commented Nov 12, 2017 at 4:23

2 Answers 2

1

I have to do such classes a lot at work, and we usually go with Adapters (correct me if I'm wrong on the design pattern). In your case, your adapter would look like this :

public class NegotiationServiceAdapter implements NegotiationInterface {

    protected $negotiationService;

    public function __construct(NegotiationService $negotiationService)
    {
        $this->negotiationService = $negotiationService;
    }

    public function resetNegotiation(Negotiation $negotiation){
        $this->negotiationService->resetNegotiation($negotiation);

        //Rest of your custom code for that client
    }
}

Notice that I added the "generic" NegotiationService used by everyone in the constructor, and then in the implemented function, you execute the code of this instance first (or last, depends on your case) and then your custom code.

Sign up to request clarification or add additional context in comments.

2 Comments

Let's say I have a customers client A and B. so client A require call a webservice method and B require export a file. How would I implement it? I was thinking about Decorator but I am not sure about it. NegotiationA, NegotiationB injecting Negotiation.
@dextervip You were close when you decided to go with the decorator pattern. Take a look at my answer for a better approach.
0

I reached at decorator pattern but I am not sure if it would be the best approach while using DI

The Composite pattern would be a better fit for this use-case as compared to the Decorator pattern. I would make the following changes to your code :

  1. Rename the resetNegotiation method to execute in NegotiationInterface and NegotiationService.
  2. Add an array or a list (that can hold NegotiationInterface instances) to NegotiationService as an instance variable.
  3. Make the constructor in NegotiationService ask for an additional list/array parameter and initialize it in the constructor.

  4. In the execute method of NegotiationService, iterate through the list and call execute on each NegotiationInterface in it.

Once you've made the above changes, you can create different implementations of NegotiationInterface add them to an array/list and pass this into NegotiationService which will simply iterate through each instance one by one and call execute on each of the instances.

For example :

$resetNegotiation = new ResetNegotiationNegotiationInterfaceImpl();
$callWebservice = new CallWebServiceNegotiationInterfaceImpl();
$negotiationInterfacesClient1 = array($resetNegotiation, $callWebservice);
$negotiationServiceClient1 = new NegotiationService($dependencies, $negotiationInterfacesClient1);
negotiationServiceClient1.execute($negotiation);

$exportFile = new ExportFileNegotiationInterfaceImpl();
$negotiationInterfacesClient2 = array($resetNegotiation, $exportFile);
$negotiationServiceClient2 = new NegotiationService($dependencies,$negotiationInterfacesClient2);
negotiationServiceClient2.execute($negotiation);

Where :

  • ResetNegotiationNegotiationInterfaceImpl implements NegotiationInterface and contains code to reset the service in the execute method. This is reused by client and client2.
  • CallWebServiceNegotiationInterfaceImpl implements NegotiationInterface and contains code to call the webservice in the execute method.
  • ExportFileNegotiationInterfaceImpl implements NegotiationInterface and contains code to export a file in the the execute method.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.