Я знаю, что проблема, о которой идет речь, неоднократно рассматривалась, поэтому очевидно, что она не такая тривиальная, как ее часто считают...
Чтобы прояснить ситуацию, я подумал, что буду строить примеры трех различных реализаций (простой фабричный, заводский метод, абстрактная фабрика), используя одно и то же семейство компонентов и одну и ту же концепцию,
Что вы думаете о следующих примерах? Вы находите их ясными и правильными?
Для всего примера я буду использовать это семейство бобов
interface Vehicle
{
public void drive();
public void clean();
}
class Car implements Vehicle
{
@Override
public void drive()
{
System.out.println("Driving a car...");
}
@Override
public void clean()
{
System.out.println("Cleaning a car...");
}
}
class Bus implements Vehicle
{
@Override
public void drive()
{
System.out.println("Driving a Bus...");
}
@Override
public void clean()
{
System.out.println("Cleaning a Bus...");
}
}
ПРОСТАЯ ФАБРИКА
/*client snippet*/
Vehicle car = VehicleFactory.getVehicle("small");
/*our factory*/
class VehicleFactory
{
public static Vehicle getVehicle(String criteria)
{
if ( criteria.equals("small") )
return new Car();
else if ( criteria.equals("big") )
return new Bus();
return null;
}
}
ЗАВОДСКИЙ МЕТОД
//client Class
public class FactoryMethodPattern
{
public static void main(String[] args)
{
//handleCreator(new ConcreteCreator1())
handleVehicle(new CarFactory());
handleVehicle(new BusFactory ());
}
//handleCreator(Creator creator)
static void handleVehicle(VehicleDriver2 vDriver)
{
System.out.println("Handling a new vehicle. Pre lambda way");
vDriver.driveVehicle();
vDriver.cleanVehicle();
}
}
//client snippet
VehicleFactory v = new CarFactory();
Vehicle vehicle = v.getVehicle();
OR
VehicleFactory v = new CarFactory();
v.driveVehicle();
//creator
abstract class VehicleFactory
{
//the abstract method of the creator
public abstract Vehicle getVehicle();
public void driveVehicle()
{
getVehicle().drive();
}
public void cleanVehicle()
{
getVehicle().clean();
}
}
//concrete creator
class CarFactory extends VehicleFactory
{
@Override
public Vehicle getVehicle()
{
return new Car();
}
}
//concrete creator
class BusFactory extends VehicleFactory
{
@Override
public Vehicle getVehicle()
{
return new Bus();
}
}
АБСТРАКТНАЯ ФАБРИКА
Для абстрактного заводского примера я добавляю эти компоненты
interface Fuel
{
public void combust();
}
class Petrol implements Fuel
{
@Override
public void combust()
{
System.out.println("Petrol...");
}
}
class Gas implements Fuel
{
@Override
public void combust()
{
System.out.println("Gas...");
}
}
И вот пример абстрактного завода
//AbstractFactory
public abstract class AbstractFactory
{
abstract Fuel getFuel(String criteria);
abstract Vehicle getVehicle(String criteria) ;
}
//ConcreteFactory
public class VehicleFactory extends AbstractFactory
{
@Override
public Vehicle getVehicle(String criteria)
{
if(criteria == null)
{
return null;
}
if(criteria.equals("BIG"))
{
return new Bus();
}
else if(criteria.equals("SMALL"))
{
return new Car();
}
return null;
}
@Override
Color getFuel(String criteria)
{
return null;
}
}
//ConcreteFactory
public class FuelFactory extends AbstractFactory
{
@Override
public Vehicle getVehicle(String criteria)
{
return null;
}
@Override
Fuel getFuel(String criteria)
{
if(criteria == null)
{
return null;
}
if(criteria.equals("CHEAP"))
{
return new Gas();
}
else if(criteria.equals("EXPANSIVE"))
{
return new Petrol();
}
return null;
}
}
public class FactoryProducer
{
public static AbstractFactory getFactory(String criteria)
{
if(criteria.equalsIgnoreCase("VEHICLE"))
{
return new VehicleFactory();
}
else if(criteria.equalsIgnoreCase("FUEL"))
{
return new FuelFactory();
}
return null;
}
}
//client class
public class AbstractFactoryPatternDemo
{
public static void main(String[] args)
{
AbstractFactory vehicleFactory = FactoryProducer.getFactory("VEHICLE");
Vehicle car = vehicleFactory.getVehicle("SMALL");
car.dirve();
AbstractFactory fuelFactory = FactoryProducer.getFactory("FUEL");
Fuel petrol = colorFactory.getFuel("EXPANSIVE");
petrol.combust
}
}
Ваши примеры хороши. Я предлагаю использовать константы или даже enum
для критериев, чтобы избежать необходимости запоминать строки и избегать орфографических ошибок.
Что-то вроде:
public class VehicleFactory {
public enum Criteria{
SMALL,BIG
}
public static Vehicle getVehicle(Criteria criteria)
{
if ( criteria.equals(Criteria.SMALL) )
return new Car();
else if ( criteria.equals(Criteria.BIG) )
return new Bus();
return null;
}
}
И клиентский код:
VehicleFactory.getVehicle(VehicleFactory.Criteria.SMALL);
Более того, я думаю, вы имеете в виду "дорогие", так как это "дешево", но уверен, что бензин тоже экспансивный :)