2

A Model object which has some private internal state. A component of this state is exposed to the clients. But one of the clients wants a different component of the internal state to be exposed. How should this be dealt with?An example

public GarageModel {
    private Vehicle car;
    private Vehicle truck;

    public Vehicle getMostInterestingVehicle() {
        //exposes car as the most interesting vehicle but
        //one of the client wants this to return a truck
        return car;
    }
}
Sebastian Piu
  • 7,838
  • 1
  • 32
  • 50
  • Why not using just different build flags and put the implementation under `#ifdef CUSTUMER_A_BUILD ... #else ... #endif` – Alex Lop. Sep 18 '15 at 04:55

4 Answers4

1

You could provide method with parameters which will define criteria by which your client sees most interesting vehicle.

public Vehicle getMostInterestingVehicleByCriteria(VehicleCriteria vehicleCriteria){
    // logic which selects correct vehicle in simple way it will be just
    if(vehicleCriteria.getMostInterestingVehicleType().equals(VehicleType.TRUCK){
        //do your logic
    }
    // In case of multiple objects you should refactor it with simple inheritance/polymorphism or maybe use some structural pattern 
}

public class VehicleCriteria{
    VehicleType mostInterestingVehicle; // enum with desired vehicle type

    public VehicleCriteria(VehicleType mostInterestingVehicle){
        this.mostInterestingVehicle = mostInterestingVehicle;
    }
}
Marcin Szymczak
  • 11,199
  • 5
  • 55
  • 63
  • thanks, one issue with this approach is when the internal state of model contains not just two but many types of vehicles, we would end up writing if, else statements for each type. – themanwhosoldtheworld Sep 18 '15 at 05:39
  • You could overcome this with inheritance, polymorphism or some structural pattern. In case of two objects both solutions may be correct. – Marcin Szymczak Sep 18 '15 at 05:42
  • This answer appears to be an attempt at illustrating the [Strategy pattern](https://sourcemaking.com/design_patterns/strategy). When the internal state of the model contains many vehicles, they can be collected into a list. The `VehicleCriteria` filter simply iterates through the list until it finds a match. – jaco0646 Sep 18 '15 at 18:10
1

If the client knows what type it wants, then let the client say so with a generic argument (C# assumed):

public T getMostInterestingVehicle<T>() where T : Vehicle { }

You can then use a dictionary of 'things' (factories maybe?) that will get a vehicle, keyed by the type they return. This could be a static collection created on construction or resolved by IoC:

private Dictionary<T, Vehicle> _things;

You can then use this to do the work:

public T getMostInterestingVehicle<T>() where T : Vehicle 
{ 
    FactoryThing thing;

    if (_things.TryGetValue(T, out thing))
    {
        return thing.GetVehicle();
    }
}

Apologies if it's not C# you're working with and if the syntax/usage is incorrect, but I think you'll get my point...

David Osborne
  • 6,436
  • 1
  • 21
  • 35
1

It is hard to say given your sample, you could apply a strategy pattern on your GarageModel class for each different client and override that single method to cater to each of their needs. This only works if you can provide different garage models to your clients though.

Polymorphism is always the answer as a teacher of mine used to say

An example would be

public TruckGarageModel: GarageModel {
    public override Vehicle getMostInterestingVehicle(){
        return truck;
    }
}

public CarGarageModel: GarageModel {
    public override Vehicle getMostInterestingVehicle(){
        return car;
    }
}

Then you would pass the appropriate decorated version of your GarageModel to each different client

Sebastian Piu
  • 7,838
  • 1
  • 32
  • 50
  • 1
    Sub-classing the `GarageModel` is a good answer, but a subclass is not the same thing as a decorator. The Decorator pattern is something more. – jaco0646 Sep 18 '15 at 18:02
  • You are right, it should be passing the original instance to be a decorator. This is more a strategy. I'll edit when on my pc – Sebastian Piu Sep 18 '15 at 21:41
  • A subclass is not a strategy either. This is basic polymorphism. No design pattern is present, and none is needed. – jaco0646 Sep 19 '15 at 16:15
0

You might have to consider quite a few things before making a decision about the implementation, some questions are these-

  • Do you expect newer implementations of Vehicle to be added later?: If yes, you might have to provide a factory that could register newer types without you making changes in the factory again and again. This provides an example. That way you avoid many if-else as well.
  • Do you want to decide what Vehicle to return at runtime?: Then Strategy Pattern helps as pointed in other answers.

Hope this helps a little bit.

User2709
  • 573
  • 5
  • 17