typedef int EngineId;

// Добавит машину в систему и вернет ее идентификатор

CarId createCar(const std::string& carType)

{

Car* car = CarFactory::create(carType);

if (!car)

return InvalidCarId;

CarManager::instance(). addCar(car);

return car->getId();

}

// Удалит машину

bool removeCar(CarId carId)

{

Car* car = CarManager::instance(). getCar(carId);

if (!car)

return false;

CarManager::instance(). removeCar(car);

delete car;

return true;

}

// Вернет стоимость автомобиля с идентификатором car

float getCarCost(CarId carId)

{

Car* car = CarManager::instance(). getCar(carId);

if (!car)

return 0;

return CarManager::instance(). getCostCalculator()->

calculateCost(car);

}

// Добавит двигатель engineType к автомобилю

// с идентификатором car

EngineId addEngineToCar(CarId carId, const std::string&

engineType)

{

Car* car = CarManager::instance(). getCar(carId);

if (!car)

return InvalidEngineId;

Engine* engine = EngineFactory::instance().

create(engineType);

if (!engine)

return InvalidEngineId;

car->addEngine(engine);

return engine->getId();

}

// Вернет полный список параметров двигателя

bool getEngineParameters(EngineId engine, EngineParams&

params)

{

Engine* engine = EngineFactory::instance().

create(engineType);

if (!engine)

return false;

params.power = engine->getPower();

params.fuelConsumption = engine->getFuelConsumption();

...

return true;

}

...

};

Как вы видите, класс-фасад должен защищать клиента от любого знания о подсистеме, поэтому он вводит новые понятия, такие, как CarId и EngineId. Это сделано, чтобы клиенты ничего не знали про реальные иерархии классов Car и Engine, а работали с подсистемой посредством этих идентификаторов, что тоже снижает уровень связанности и создает устойчивый интерфейс.

Ясно, что для большой подсистемы такой класс-фасад окажется огромным, но зато это будет единственная точка связывания подсистемы с клиентским кодом. А значит, все внутренние изменения подсистемы будут проходить незаметно и безболезненно, без возможности разрушить интерфейс, используемый клиентами.

Кроме того, наличие такого класса-фасада позволяет полностью изменить (например, переписать с нуля) реализацию подсистемы, причем сделать это становится гораздо проще благодаря слабому связыванию с клиентским кодом.

«Приспособленец»

Паттерн «Приспособленец» (Flyweight) используется, если надо уменьшить число объектов в системе. Когда объектов становится так много, что накладные расходы превышают лимиты, например, на память, то надо найти способ, как хранить меньше объектов и иметь ту же функциональность.

Этого можно достичь, если вынести из объектов контекстнозависимые параметры и параметры состояния. Это позволит во много раз сократить число объектов, но добавит накладные расходы на передачу в них контекста, так как контекст теперь будет храниться у клиентов.

Например, предположим, что мы в каждом автомобиле моделируем все детали, в том числе болты. В итоге уже через несколько минут работы программы в ней имеются миллионы объектов типа Bolt. Через 1– 2 ч это уже может стать проблемой и даже привести к MemoryOverflow (см. листинг 7).

Листинг 7

class Bolt

{

BoltType mType; // тип болта

float mWeight; // масса болта

Car* mCar; // в какой машине установлен

bool mWellTwisted; // хорошо ли закручен

Position mPosition; // позиция в 3-D пространстве относительно центра авто

...

public:

Bolt(BoltType type, float weight, Car* car, bool wellTwisted, const Position& pos) {...};

virtual void draw()

{

Position pos = mCar->getPosition() + mPosition;

DrawSystem::instance(). drawBolt(mType, pos);

};

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату
×