如何使用工厂模式

本文关键字:模式 工厂 何使用 | 更新日期: 2024-11-08 20:11:48

可能的重复项:
.NET Framework 中的构造函数与工厂

我了解工厂模式并实施了它,但无法获得它将带来什么好处。例如,代替:

MyType1 obj=new Mytype1();
MyType2 obj=new Mytype2();

写作:

IMyType obj1 = Factory.Create(1);
IMyType obj2 = Factory.Create(2);

是我错过了还是没有想到。你能不能举你自己的经验例子。

如何使用工厂模式

工厂模式的一些好处:

  1. 您可以跟踪您创建的对象。 如果要重用对象或对创建的对象数实施限制,工厂可以强制执行。
  2. 您可以控制对象的创建方式。 如果有一些参数用于创建对象,则可以在客户端为已创建的对象传入相同的参数时返回现有对象。
  3. 您可以让工厂返回接口,但在内部创建支持该接口的不同类型的对象。

工厂模式很好,原因有很多

其中有几个是:

  • 您可以在工厂中初始化项目(默认值等)并使项目创建过程化(查看其他类/过程,获取默认值,检查配置值)。

构造函数是创建项的一种方法,但如果不将类与这些依赖项紧密耦合,则无法检查新创建的实例之外的其他类或运行其他进程

  • 它为项目创建提供了一个中央存储库,可在团队中的开发人员之间强制实施模式/实践

这些是我能想到的一些原因:)

例如

此类依赖于 ConfigManager 进行实例化

class SomeClass 
{
    public int SomeValue;
    public SomeClass() 
    {
        // Check the config for some value
        SomeValue = ConfigManager.GetDefaultInt("SomeValue");
    }
}

此类不是因为它使用工厂

class SomeClass 
{
    public int SomeValue;
    public SomeClass() 
    {
    }
}
class SomeClassFactory 
{
    public SomeClass CreateSomeClass() 
    {
        SomeClass obj = new SomeClass();
        obj.SomeValue = ConfigManager.GetDefaultInt("SomeValue");
    }
}

工厂模式的好处是,它封装了构造和特定类型的详细信息。 这使您可以在以后发展到更有趣的设计,而进行更改的地方更少。

请考虑以下示例:

public interface IStorage
{
    void Save(SomeObject toSave);
    SomeObject Get(SomeId id);
}
public class DatabaseStorage : IStorage
{
    public void Save(SomeObject toSave)
    {
       //persist to DB somehow
    }
    public SomeObject Get(SomeId id)
    {
       //get from db somehow and return
    }
}
public class StorageFactory
{
    public IStorage GetStorage()
    {
         return new DatabaseStorage();
    }
}
public class DatabaseStorage : IStorage
{
    public void Save(SomeObject toSave)
    {
       //persist to DB somehow
    }
    public SomeObject Get(SomeId id)
    {
       //get from db somehow and return
    }
}

现在假设您稍后需要缓存一些结果或记录所有结果。 您可以创建一个代理,如下所示:

public class LoggingStorage : IStorage
{
    private readonly IStorage _proxied;
    public LoggingStorage(IStorage proxied)
    {
        _proxied = proxied;
    }
    public void Save(SomeObject toSave)
    {
       //log this call
       _proxied.Save(toSave);
    }
    public SomeObject Get(SomeId id)
    {
       //log this call
       return _proxied.Get(id);
    }
}

现在,如果你使用了一个构造函数,你必须替换它的每一次使用来包装它。 如果您使用工厂,则只需更改它:

public class StorageFactory
{
    public IStorage GetStorage()
    {
         return new LoggingStorage(new DatabaseStorage());
    }
}

当然,投机工厂似乎有点沉重,这就是为什么我更喜欢封装构造函数。

jQuery是一个工厂函数,它利用JavaScript的工作方式来创建内存占用非常低的对象。

让我们用一个非常残缺的、急剧简化的jQuery版本来研究一下,以帮助看到潜在的好处:

var $ = jQuery = (function(){ //this anon function fires once, and returns a function
//defines all kinds of internal functions jquery uses here
function jQuery(selector,context){ // we're going to return this inner JQ later
    //defines only the logic needed to decide what to do with the arguments here
    //and then builds the jQuery object with 'return new jQuery.prototype.init();'
}
//defines jQuery.prototype properties here:
jQuery.prototype = {
    //...
    init:function(selector,context){ //gets used to build the JQ objects
        this.constructor.prototype = jQuery.prototype; //hands off the function prototype
    }
    //...
}
return jQuery; //this gets assigned to the outer jQuery and $ vars
})()

所以......现在我们有一个工厂函数,它也类似于命名空间,我们可以扩展其原型,并期望这些方法在它吐出的对象上可用。此外,除了它们通常包装的 DOM 对象之外,对象本身在内存中的权重很小,因为所有函数都是从闭包中提取的引用或作为引用传递的外部原型对象。除了一些逻辑和一些状态变量之外,对象所需的一切都是在jQuery首次从原型对象解析或传递时构建的,因为您将新方法添加到工厂函数的原型属性。

现在,尝试用new jQuery()来做到这一点

如果有的话,在 JavaScript 中应用工厂模式可以非常强大且独特。