Следующий код - это своего рода заводская модель для D, использующая шаблоны, что подразумевает создание легко подключаемых объектов.Static Factory Pattern
Как есть, код не является надежным (множественное наследование, зависимости и т. Д.).
Я бы хотел, чтобы он работал в более общих и общих настройках, таких как наличие определенного типа списка зависимостей для разных объектов/типов (я установил код для этого пути, используя gui и кнопочный сценарий).
Я также думаю, что есть, вероятно, некоторый способ справиться с сохранением и восстановлением данных, но я не совсем уверен, как подойти к нему. Было бы лучше, чтобы каждый объект сериализовал свои данные и сохранил их в базе данных или имел один глобальный магазин, который обрабатывает все это? (Я думаю, что сохранение только изменений от значения по умолчанию важны)
В любом случае, может быть, у кого-то есть какие-то полезные идеи, которые помогут мне в правильном направлении?
(как и код, который почти идентичен используемому на заводе, поскольку любая реализация iGui может быть подключена. Я называю это статическим заводским шаблоном просто потому, что все настройки выполняются за кулисами в основном во время компиляции (через шаблоны))
module main;
import std.file, std.stdio;
// Mixin iStaticFactory into an interface to provide generic pluggable derived instantiation.
// Must use New(id, data) as a way to instantiate a new object of type A(specified by ID) : T. New() is allowed but only provides
// default type and is not pluggable. A msg is given anywhere New() is used(should only be used when pluggability is not desired) or during mock up.
//
// The corresponding mixin template cStaticFactory must be used in all derived types that are to be pluggable.
//
// The user must provide a way to store and retrieve the object data to allow generic and configurable pluggability. As is,
// any derived type of T may be substituted for T dynamically.
//
// D is the default object type to use
mixin template iStaticFactory(D)
{
alias T = typeof(this);
static assert(is(D : typeof(this)), "iStaticFactory: "~std.traits.fullyQualifiedName!(D)~" must inherit from "~std.traits.fullyQualifiedName!(typeof(this)));
@property string _getID(); // returns the type name for this object
static final T function(string data)[string] _Creators; // An AA of functions that are registered by the classes which are desired to be plugged into the interface T.
// Generic New function that returns an initiated instance of a derived type of T corresponding to data.ID.
static final T New(string file = __FILE__, size_t line = __LINE__, string mod = __MODULE__)(string id, string data = null)
{
if (id != null && id in _Creators) return _Creators[id](data);
return D.New(null); // provides default type
}
// Non-Generic New function returning a default derived type of T used for testing purposes or default object
static final T New(string file = __FILE__, size_t line = __LINE__, string mod = __MODULE__)()
{
pragma(msg, "StaticFactory: Not pluggable at "~mod~":"~std.string.chomp(line.stringof, "u")~" ["~file~"]");
return New(null);
}
}
// Mixin cStaticFactory into any class to provide pluggability.
mixin template cStaticFactor()
{
alias A = typeof(this);
// Assume if A has a _Creators member, New member, and _getID member then it inherits from an interface using iStaticFactory
static assert(std.traits.hasMember!(A, "_Creators") & std.traits.hasMember!(A, "New") & std.traits.hasMember!(A, "_getID"), "cStaticFactory: "~std.traits.fullyQualifiedName!(A)~" must inherit from a Static Factory!");
enum _ID = std.traits.fullyQualifiedName!A;
@property string _getID() { return _ID; }
// Registers this class with the _Creators of T's StaticFactory allowing it to be used to create it's own type.
static this() { A._Creators[_ID] = &New; }
// Creates and instantiates this type with data. Override to instantiate data.
static final T New(string data) { A t = new A; if (data == null) return t; return t; }
}
// Demo:
interface iGui { mixin iStaticFactory!(WindowsGui); void foo(); }
class WindowsGui : iGui { mixin cStaticFactor; void foo() { writeln("-------Called from "~std.traits.fullyQualifiedName!(typeof(this))); } }
class LinuxGui : iGui { mixin cStaticFactor; void foo() { writeln("-------Called from "~std.traits.fullyQualifiedName!(typeof(this))); } }
interface iButton { mixin iStaticFactory!(WindowsButton); void foo(); }
class WindowsButton : iButton { mixin cStaticFactor; void foo() { writeln("-------Called from "~std.traits.fullyQualifiedName!(typeof(this))); } }
class LinuxButton : iButton { mixin cStaticFactor; void foo() { writeln("-------Called from "~std.traits.fullyQualifiedName!(typeof(this))); } }
void main()
{
import std.traits;
enum fnGui = "guiSFdata.tmp";
enum fnButton = "butSFdata.tmp";
// load/create our gui object.
iGui a = iGui.New(exists(fnGui) ? cast(string)read(fnGui, 100) : null);
// Display object's typeDo something with the object
writeln("Current object type is "~a._getID~"["~(exists(fnGui) ? cast(string)read(fnGui, 100) : "new")~"] with output :");
a.foo();
// Provide mechanism to change object
foreach(k, v; iGui._Creators)
{
if (k == a._getID) continue;
writeln("Would you like to change to "~k~" [y/n]"); if (readln()[0] == 'n') continue;
// Set a to new object type, assume no data
a = v(null);
std.file.write(fnGui, a._getID);
writeln("Changed to "~k~"");
break;
}
}
Спасибо. используется интерфейс istatic, так что статический это не переопределяется непреднамеренно. Если класс имеет значение static, и он не регистрирует класс, тогда класс не может использоваться при создании самого. Использование интерфейса просто гарантирует, что обработчики всегда зарегистрированы. – user3252407
Я не думаю, что object.factory помогает здесь, потому что он не дает возможности инициализировать объект, а также, вероятно, использует GC для создания объектов. – user3252407
Вы можете иметь столько статических конструкторов в классе, сколько хотите. Они не будут переопределять или конфликтовать друг с другом и будут работать в том порядке, в котором они объявлены. 'Object.factory' вызывает конструктор по умолчанию класса, который может выполнять любую инициализацию, в которой вы нуждаетесь. –