下面的代码是D的一种工厂模式,它使用模板,这意味着可以轻松地插入对象。
实际上,代码不是健壮的(多重继承、依赖等)。
我希望它能够在更一般和更常见的环境中工作,比如为不同的对象/类型设置某种类型的依赖列表(我已经设置了代码,使用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;
}
}发布于 2014-01-30 09:52:22
不管怎样,也许有人有一些有用的想法能让我走向正确的方向?
这里有几个:
typeof(this),这意味着不需要将当前对象的类型作为参数传递给混合器。static interface iStaticFactory,因为每个类可以有多个static this。shared static this将更合适,因为它将在程序启动时而不是在每个线程的启动时注册组件。我还认为,可能有一些方法可以更容易地处理数据的保存和恢复,但我不太清楚如何处理它。
我刚刚完成了我的持久性模块的大修,也许您可以在这里找到一些有用的东西(有关使用示例,请参阅单元测试)。
https://stackoverflow.com/questions/21452759
复制相似问题