Using a class to store constant values

98 Views Asked by At

Is there a better approach to storing values required as per the following example. Im trying to avoid any possible errors when passing the string to factory method.

But, are there any issues with this? Is it easily testable, is there a better way to achieve the same thing etc.

abstract class Types
{
    const Car = 'car';
    const Boat = 'boat';
    const Bike = 'bike';
}

class VehicleFactory {

    public function make($type) 
    {
        if ($type === Types::Car) {
            // create new car
        }
        if ($type === Types::Boat) {
            // create new Boat
        }
        if ($type === Types::Bike) {
            // create new Bike
        }
    }
}

class Client
{
    public function createACar()
    {
        $vehicleFactory = new VehicleFactory();
        $car = $vehicleFactory->create(Types::Car)
    }
}
1

There are 1 best solutions below

2
On BEST ANSWER

This looks like a language agnostic question so I am going to assume that advice like use an enum instead of an abstract class won't work.

Your approach of using constants to represent what type of object gets created is correct. If I had to change anything, it would be the way your Client class uses the VehicleFactory so as to provide test doubles while unit testing your code :

class Client
{

    private $factory;

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

    public function createACar()
    {
        $car = $factory->create(Types::Car)
    }
}

Now you can pass in a subclass of VehicleFactory (say VehicleMockFactory) that can create test doubles instead of creating the actual objects :

class VehicleMockFactory extends VehicleFactory {

    public function make($type) 
    {
        if ($type === Types::Car) {
            // create new TestCar
        }
        if ($type === Types::Boat) {
            // create new TestBoat
        }
        if ($type === Types::Bike) {
            // create new TestBike
        }
    }
}

While unit testing, you can pass VehicleMockFactory to the Client rather than the actual VehicleFactory.