标签: factory-pattern

在使用工厂模式时,我应该以任何方式避免向下转型吗?

我正在开发一个实现专有协议的服务器项目。服务器是用C++实现的工厂模式,我们现在面临着向下转型的问题。

我正在研究的协议是为自动控制慢速网络而设计的,例如RS485、ZigBee、窄带PLC 等。我们设计了工厂模式的主服务器。当接收到新帧时,我们首先识别该帧的关联设备类型,调用工厂方法生成新的“解析器”实例,并将帧分派给解析器实例。

我们的专有协议是纯二进制实现的,我们可能需要的每一个信息都记录在帧本身中,因此可以尽可能简单地定义基本接口。我们还将为我们的工厂实现自动注册方法(此处省略了与 std::map 操作相关的详细代码):

// This is our "interface" base-class
class parser
{
public:
    virtual int parse(unsigned char *) = 0;
    virtual ~parser() { }
};

// The next two classes are used for factory pattern
class instance_generator
{
public:
    virtual parser *generate() = 0;
};

class parser_factory
{
private:
    static std::map<int,instance_generator*> classDB;
public:
    static void add(int id, instance_generator &genrator);
    parser *get_instance(int id);
};

// the two template classes are implementations of "auto-regisrtation"
template <class G, int ID> …
Run Code Online (Sandbox Code Playgroud)

c++ oop downcast factory-pattern

5
推荐指数
1
解决办法
1438
查看次数

暴露多个接口的技术(通过静态创建方法)

我目前正在做一个项目,在该项目中我试图隐藏尽可能多的关于我创建的层次结构的细节。我想这样做是为了最大限度地减少用户需要了解的有关对象的信息量(并控制他们可以对对象状态执行的操作)。此外,我使用该模式来限制应用程序可以创建的对象类型,并将其限制为从工厂创建。

然而,我遇到的主要问题是我想公开几种不同类型的接口。每个接口都有我认为不应共享的附加功能,我希望将这些接口分开。最后,我不知道将来会出现哪些新界面,但我想尝试并为它们做好准备。

Weapon

public interface Weapon extends GameObject {
    Number attack();

    boolean addWeaponAttribute(WeaponAttribute attribute);
}
Run Code Online (Sandbox Code Playgroud)

Firearm

public interface Firearm extends Weapon {
    void reload(Number rounds);
}
Run Code Online (Sandbox Code Playgroud)

我的问题是让工厂生产具有不同接口的对象的最佳方法是什么?这就是我在想“最好的”:

  1. 用户最清楚(很明显他们要求什么以及他们得到什么)
  2. 未来扩展的最佳选择(我不确定我将向该系统添加哪些新接口)。

到目前为止,这是我一直在想的:

为每个接口创建正确命名的方法

public static Firearm getFirearm(String firearmName) {
    ...
}

public static Weapon getWeapon(String weaponName) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

执行上述操作,但在单独命名的类中生成工厂

public class WeaponFactory {
    public static Weapon getWeapon(String weaponName) {
        ...
    }
}


public class FirearmFactory {    
    public static Firearm getFirearm(String firearmName) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

完全不同的东西

我愿意接受建议和改变。这是一个灵活的项目,因此我可以随心所欲地进行更改(就项目的这一部分而言)以取得更好的结果。

另外 - …

java design-patterns factory-pattern

5
推荐指数
1
解决办法
1435
查看次数

Cocoa 单例和协议

我想定义一个协议并创建一种简单、标准的方法来获取所述协议的“默认”共享实现 - 单例样式。Cocoa 遵循以下模式:

[NSUserDefaults standardUserDefaults]
[NSNotificationCenter defaultCenter]
Run Code Online (Sandbox Code Playgroud)

但在这两种情况下,它们在对象层次结构的底部都有@interfaces。我正在努力解决如何使用@protocols 来做到这一点。显然,我可以创建一个具有空或简单方法实现的类 - 但实际上,我想要的是层次结构底部的 @protocol。我尝试过类似的事情:

@protocol ConfigurationManager <NSObject>

//...

@interface ConfigurationManagerFactory : NSObject

+ (id<ConfigurationManager>)sharedConfiguration;

@end

// ...

id<ConfigurationManger> config = [ConfigurationManagerFactory sharedConfiguration];
[config ...];
Run Code Online (Sandbox Code Playgroud)

它有效 - 但我总是必须解释如何使用它以及为什么我这样做。有没有一种方法可以符合 Cocoa 的语法(调用约定),同时仍然利用 @protocols 的价值?

顺便说一句,我是否有理由不想像这样使用@protocols?实现 @interface 仍然可以利用类别和替代实现等 - 就像实例化 NSString 通常会留下一个扩展 NSString 的类一样。

cocoa singleton objective-c factory-pattern ios

5
推荐指数
1
解决办法
1130
查看次数

在注入之前在工厂内调用类的初始化方法是一个很好的设计选项

我正在重构相当大部分的意大利面条代码.简而言之,它是一个很大的"上帝之类"类,根据某些条件分为两个不同的过程.这两个过程都很冗长,并且有很多重复的代码.

所以我的第一个努力就是将这两个进程提取到他们自己的类中,并将公共代码放在他们都继承的父代中.

它看起来像这样:

public class ExportProcess
{
   public ExportClass(IExportDataProvider dataProvider, IExporterFactory exporterFactory)
   {
       _dataProvider = dataProvider;
       _exporterFactory = exporterFactory;
   }

   public void DoExport(SomeDataStructure someDataStructure)
   {
      _dataProvider.Load(someDataStructure.Id);

      var exporter = _exporterFactory.Create(_dataProvider, someDataStructure);

      exporter.Export();
   }
}
Run Code Online (Sandbox Code Playgroud)

我是Mark Seemann博客的狂热读者,在这篇文章中他解释说这段代码具有时间耦合气味,因为在数据提供程序处于可用状态之前必须调用Load方法.

基于此,并且由于对象被注入到工厂返回的对象中,我正在考虑更改工厂来执行此操作:

public IExporter Create(IExportDataProvider dataProvider, SomeDataStructure someDataStructure)
{
   dataProvider.Load(someDataStructure.Id);

   if(dataProvider.IsNewExport)
   {
      return new NewExportExporter(dataProvider, someDataStructure);
   }
   return new UpdateExportExporter(dataProvider, someDataStructure);
}
Run Code Online (Sandbox Code Playgroud)

由于名称"DataProvider",您可能猜到Load方法实际上正在进行数据库访问.

有些东西告诉我在抽象工厂的create方法中进行数据库访问的对象不是一个好的设计.

是否有任何指导方针,最佳做法或某些事情表明这实际上是一个坏主意?

谢谢你的帮助.

c# refactoring factory-pattern

5
推荐指数
1
解决办法
123
查看次数

工厂应该有一个带参数的构造函数吗?

假设我想构建一个字符串列表(这不是真实的情况,但听起来更简单).

我的字符串工厂列表的界面看起来像这样

public interface IStringsListFactory{
   List<string> Create();
}
Run Code Online (Sandbox Code Playgroud)

但是,让我说我的一个具体工厂需要从文件/数据库等获取这个字符串列表.

public class StringsListFromFile : IStringsListFactory{

   private StreamReader _streamReader;
   public StringsListFromFile(StreamReader sr) //StreamReader is just an example.
   {
       _streamReader = sr;
   }

   public List<string> Create(){ 
     ///recover the strings using my stream reader... 
   }
}
Run Code Online (Sandbox Code Playgroud)

我知道这种方法可行,但我想知道它是否会破坏工厂模式以将参数传递给工厂的构造函数,所以我不会破坏我的界面.这样做有没有对应的?还有其他解决方案我没有想到吗?我问了太多问题!?!(是的,我知道这个的答案!)

c# design-patterns factory-pattern

5
推荐指数
1
解决办法
7409
查看次数

这是哪种设计模式:工厂方法还是抽象工厂

我正在阅读有关创建性设计模式的文章,并设法在 Factory 、 Abstract Factory 和 Factory 方法之间完全混淆了自己。

我在下面发布了一个代码片段。有人愿意让我知道这是哪一个以及(如果可能)可以对代码进行哪些更改以使其属于其他类别?

#include "iostream.h"

#define QUIT 2

class Shape {
public:
    virtual void draw() = 0;
};

class Circle : public Shape {
public:
    void draw() {
        cout << "circle : draw" << endl;
    }
};
class Square : public Shape {
public:
    void draw() {
        cout << "square : draw" << endl;
    }
};

class Factory {
public:
    virtual Shape* createInstance(int id) = 0;
};

class SimpleShapeFactory : public Factory {
public: …
Run Code Online (Sandbox Code Playgroud)

c++ design-patterns factory-pattern

5
推荐指数
1
解决办法
439
查看次数

用于从不同来源读取数据并将其发送到不同目的地的系统的 OOP 设计

我正在编写一个 java 软件,它就像一个中间件,用于从不同来源收集数据,然后处理数据并将其发送到不同的目的地。

数据源和目的地包括:文件、数据库、TCP、HTTP。

用户将能够创建一个通道,每个通道将有一个数据源(文件读取器、数据库读取器、tcp 侦听器)和一个或多个数据目的地(文件写入器、数据库写入器、tcp 发送器)。

渠道图

该应用程序将按以下方式工作:

  1. 从数据库中读取频道。
  2. 为每个通道创建数据源及其目标。
  3. 启动数据源读取数据。

我想到的是:

  • 源和目的地表示如下: 在此处输入图片说明
  • 通道是一个容器,将由源和目标列表注入。所以通道就像一个门面模式
  • 通道中的数据处理器将使用观察者模式连接到目的地
  • 在运行时,当应用程序从数据库加载频道列表时,我将使用工厂模式来创建源和目标。

那么,这是代表渠道、来源和目的地的最佳方式吗?我认为源和目标有相似之处,例如,FileReader 和 FileWriter 类将相同,只是一个用于读取,另一个用于写入,将它们中的每一个表示为一个单独的类是否好?

java oop design-patterns factory-pattern observer-pattern

5
推荐指数
1
解决办法
1333
查看次数

在 Python 中将包/模块作为参数传递

假设我写了一些绘图程序。该程序依赖于可以绘制图形基元的模块。但是该图形模块可以是任何支持所使用操作的东西。它可以是在屏幕上绘图或写入文件格式或用笔控制机器人的模块。

我想动态切换该模块。在 C++ 中,人们通常会使用抽象工厂模式:绘图程序接收一个工厂作为参数,从中构建所需的图形基元。在 Python 中实现工厂模式也是完全可行的。

但是 - 仅将包用作参数是个好主意吗?从纯技术的角度来看,像下面这样的程序是可行的:

import screen_graphics
import robot_graphics

def my_plot_prog(graphics_lib):
   ...

my_plot_prog(screen_graphics) # plot on screen
my_plot_prog(robot_graphics) # R/C robot with a pen
Run Code Online (Sandbox Code Playgroud)

我可以这样做吗,还是有一些严重的陷阱或更好的方法?

python factory-pattern

5
推荐指数
0
解决办法
1173
查看次数

在不知道类型的情况下返回通用对象?

我对编程还很陌生,并且一直负责创建一个 WebHook 使用者,该使用者接受原始 JSON 字符串,将 JSON 解析为一个对象,该对象将被传递到处理程序中进行处理。JSON 是这样输入的:

{
   "id":"1",
   "created_at":"2017-09-19T20:41:23.093Z",
   "type":"person.created",
   "object":{
      "id":"person1",
      "created_at":"2017-09-19T20:41:23.076Z",
      "updated_at":"2017-09-19T20:41:23.076Z",
      "firstname":"First",
      ...
   }
}
Run Code Online (Sandbox Code Playgroud)

内部对象可以是任何对象,所以我认为这将是使用泛型的好机会,并按如下方式构建我的类:

public class WebHookModel<T> where T : class, new()
{
    [JsonProperty(PropertyName = "id")]
    public string Id { get; set; }

    [JsonProperty(PropertyName = "created_at")]
    public DateTime CreatedAt { get; set; }

    [JsonProperty(PropertyName = "type")]
    public string Type { get; set; }

    [JsonProperty(PropertyName = "object")]
    public T Object { get; set; }

    [JsonIgnore]
    public string WebHookAction
    {
        get
        {
            return string.IsNullOrEmpty(Type) ? …
Run Code Online (Sandbox Code Playgroud)

c# generics factory-pattern

5
推荐指数
1
解决办法
904
查看次数

简单工厂 vs 工厂方法

简单工厂: 在此处输入图片说明

工厂方法:

在此处输入图片说明

嘿大家。我正在寻找简单工厂和工厂方法之间的区别。我知道结构差异(上图),但我无法理解用例的差异。例如,这是对工厂方法的解释:

在工厂方法模式中,我们将引入一个名为“IMobileFactory”的新接口和两个具体实现“NokiaFactory”和“IphoneFactory”。这些具体的类控制对象的创建。

在我的例子中,客户想要一个诺基亚对象。所以下面给出了步骤。

1.客户端将加载对“NokiaFactory”的引用。但是 Client 不会像 Simple Factory 模式那样直接引用“NokiaFactory”类。客户端通过接口“IMobileFactory”引用具体实现。

2.然后客户端调用'CreateMobile()'方法,该方法将返回一个'IMobile'类型的对象。

3.这里我们要通过一些配置或者参数告知客户端要使用的具体实现。

我无法理解第一步:

但是 Client 不会像 Simple Factory 模式那样直接引用“NokiaFactory”类。客户端通过接口“IMobileFactory”引用具体实现。

所以客户写了这样的东西:

IMobileFactory factory = LoadFactory("NokiaFactory");
Run Code Online (Sandbox Code Playgroud)

那么为什么它有用而且更好呢?有什么好处?为什么我不应该这样写:

NokiaFactory factory = new NokiaFactory();
Run Code Online (Sandbox Code Playgroud)

或者那怎么办:

IMobileFactory factory = new NokiaFactory();
Run Code Online (Sandbox Code Playgroud)

java oop design-patterns factory-method factory-pattern

5
推荐指数
2
解决办法
2236
查看次数