こんにちは、Habr!
私はあまり有名な専門家ではありませんが、データ処理のプロセスと、このデータを処理するためのコードの記述に非常に興味があります。このデータを処理するさまざまな方法を書く過程で、私は部分的な自動化、ええと、処理方法を書くという考えを持っていました。
前書き
ある種のデータストリームを処理したり、他の複雑なエンティティを構築したり、処理アルゴリズムを再現するためにこれらのエンティティの構成シーケンスの条件を絶えず変更したりするためのツール(エンティティ)のセットがあるとします。
例として車両を使用する
アトミックコンポーネントのセットがあります。
class EngineA;
class EngineB;
class WingsA;
class WingsB;
class FrameA;
class FrameB;
class WheelsA;
class WheelsB;
等
車が必要な場合は、目的のボディ、ホイール、エンジンなどを備えたCarクラスを宣言するだけです。ボートの場合と同様に、ボートクラスを宣言し、ボートの必要な部分の集合をすばやくスケッチします。
ボート、車、さらには飛行機が必要な場合はファクトリパターンを使用できますが、車、ボート、飛行機が必要で、何台、いつ、どのような順序であるかが事前にわからない場合はどうすればよいですか。 。
, Car, Boat, Plane ITransport. 2 , 5 - . , , . -
, !
, ITransport
class ITransport
{
public:
virtual void move() = 0;
};
Car, Boat, Plane.
class Car final : public virtual ITransport
{
public:
Car() = default;
~Car() = default;
void move() override
{
std::cout << "Car is move" << std::endl;
// do something with parts
}
private:
std::unique_ptr < IFrame > _frame;
std::unique_ptr < IWheels > _wheels;
std::unique_ptr < IEngine > _engine;
};
class Boat final : public virtual ITransport
{
public:
Boat() = default;
~Boat() = default;
void move() override
{
std::cout << "Boat is move" << std::endl;
// do something with parts
}
private:
std::unique_ptr < IFrame > _frame;
std::unique_ptr < IEngine> _engine;
};
class Plane final : public virtual ITransport
{
public:
Plane() = default;
~Plane() = default;
void move() override
{
std::cout << "Plane is move" << std::endl;
// do something with parts
}
private:
std::unique_ptr < IFrame > _frame;
std::unique_ptr < IEngine> _engine;
std::unique_ptr < IWings > _wings;
};
2 , , 3 , .
, . .
enum class VehTypes
{
Car,
Boat,
Plane
};
static std::map < std::string, VehTypes > VehCast{
{"Car", VehTypes::Car},
{"Boat", VehTypes::Boat},
{"Plane", VehTypes::Plane}
};
, .
class Conveyor final
{
public:
using _TyParameters = std::map < std::string, std::string >;
using _TyStorage = std::vector < _TyParameters >;
Conveyor(const _TyStorage& blueprints)
: _blueprints(blueprints) { }
~Conveyor() = default;
std::vector < Vehicles::ITransport* > vehicles()
{
std::vector < Vehicles::ITransport* > result;
for (auto&& blueprint : _blueprints)
{
switch (VehCast[blueprint["type"]])
{
case VehTypes::Car: result.emplace_back(new Vehicles::Car());
break;
case VehTypes::Boat: result.emplace_back(new Vehicles::Boat());
break;
case VehTypes::Plane: result.emplace_back(new Vehicles::Plane());
break;
}
}
return result;
}
private:
_TyStorage _blueprints;
};
, .
:
-
- , .
using _TyParameters = std::map < std::string, std::string >;
using _TyStorage = std::vector < _TyParameters >;
, ( ).
, - , .
( ) .
.
.
Conveyor::_TyStorage blueprints
{
{
{"type", "Car"}, {"engineType", "EngineA"}, {"wheelsType", "WheelsB"}, etc..
},
{
{"type", "Car"},
},
{
{"type", "Boat"},
},
{
{"type", "Plane"},
},
{
{"type", "Plane"},
},
{
{"type", "Plane"}
},
{
{"type", "Boat"}
},
};
Conveyor conveyor(blueprints);
for (auto&& transport : conveyor.vehicles())
{
transport->move();
}
, , .
, , / .
オブジェクトを構築するこのアプローチの弱点のうち、新しいタイプを毎回辞書に追加する必要があること、および新しいアトミックコンポーネントを絶えず追加している場合は、新しいテキストパラメーターのインタープリターを絶えず追加する必要があることに注意できます。