Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Achieve strategy pattern when we have different return type

I have SaveManager Abstract class and my concrete classes TVSaveManager, DataSaveManager and VoiceSaveManager implementing SaveManager Abstract class.

List<SaveManager> lstPrdSaveManager;

        public SaveResponseModel SaveProducts(SaveProductsRequest objSaveProductsRequest)
        {
            SaveResponseModel saveResponseModel = new SaveResponseModel();

            lstPrdSaveManager = SaveManagerFactory.GetSaveManagers(objSaveProductsRequest, saveResponseModel);

            lstPrdSaveManager.ForEach(saveManager =>
                {
                    saveResponseModel = saveManager.MapAndSaveProduct();
                });


            return saveResponseModel;
        }

Factory class will decide which manager to create and send us the list. I will loop thru the list and invoke the common interface 'MapAndSaveProduct' that every concrete classes will adhere. I guess more or like a strategy pattern.

But the thing is all the concrete savemanage's MapAndSaveProduct method return type is different. TVResponse for TvSaveManager and DataResponse for DataSaveManager and so on. So i created SaveResponseModel class to club all the return types (I am passing SaveResponseModel to factory so that it will get passed to all concrete savemanager class's constructor. Individual class will set the desired property., like TvSaveManager -> saveResponseModel.TvResponse). I get desired result and code looks clean.

Questions are, 1) Is it the correct way to use this pattern when we have different type? 2) If concrete class have different types, should not we use strategy pattern? 3) Should I approach to different design pattern in this case. if yes which one?

like image 300
Al. Avatar asked Oct 07 '22 20:10

Al.


1 Answers

You've got a combination of Strategy and Visitor in a single group of methods; this is absolutely OK. You could separate them out by giving the responses a common interface, and adding a visitor to it for harvesting the right response. This would apply two patterns in sequence, rather than applying both at the same time.

interface IResponseVisitor {
    void VisitTvResponse(TvResponse r);
    void VisitDataResponse(DataResponse r);
}
interface IResponse {
    void Accept(IResponseVisitor v);
}
class TvResponse : IResponse {
    public void Accept(IResponseVisitor v) {
        v.VisitTvResponse(this);
    }
}
class DataResponse : IResponse {
    public void Accept(IResponseVisitor v) {
        v.VisitDataResponse(this);
    }
}

Now all your MapAndSaveProduct implementations could return the common IResponse. You could collect them all, and then go through them with an implementation of IResponseVisitor, and do what you need for each type inside the corresponding Accept method.

like image 165
Sergey Kalinichenko Avatar answered Oct 13 '22 10:10

Sergey Kalinichenko