首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >静态工厂模式

静态工厂模式
EN

Stack Overflow用户
提问于 2014-01-30 09:42:48
回答 1查看 159关注 0票数 3

下面的代码是D的一种工厂模式,它使用模板,这意味着可以轻松地插入对象。

实际上,代码不是健壮的(多重继承、依赖等)。

我希望它能够在更一般和更常见的环境中工作,比如为不同的对象/类型设置某种类型的依赖列表(我已经设置了代码,使用gui和按钮场景沿着这条路径前进)。

我还认为,可能有一些方法可以更容易地处理数据的保存和恢复,但我不太清楚如何处理它。最好是让每个对象序列化其数据并将其存储在数据库中,还是有一个处理所有数据的全局存储?(我认为只存储来自缺省值的更改是非常重要的)

不管怎样,也许有人有一些有用的想法能让我走向正确的方向?

(正如所述,代码的工作方式与使用工厂几乎相同,因为iGui的任何实现都可以插入。我称之为静态工厂模式,因为所有的设置都是在幕后完成的,主要是在编译时(通过模板)完成的。

代码语言:javascript
复制
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;
    }

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-30 09:52:22

不管怎样,也许有人有一些有用的想法能让我走向正确的方向?

这里有几个:

  • 请查看Object.factory,它只允许使用类的完全限定名创建类。
  • 您可以在混合模板中使用typeof(this),这意味着不需要将当前对象的类型作为参数传递给混合器。
  • 我看不出有什么理由使用static interface iStaticFactory,因为每个类可以有多个static this
  • 除非您的程序只使用一个线程,否则shared static this将更合适,因为它将在程序启动时而不是在每个线程的启动时注册组件。

我还认为,可能有一些方法可以更容易地处理数据的保存和恢复,但我不太清楚如何处理它。

我刚刚完成了我的持久性模块的大修,也许您可以在这里找到一些有用的东西(有关使用示例,请参阅单元测试)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21452759

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档