我想知道工厂模式是否存在相反的模式.例如,当需要删除某个对象时,需要完成一些额外的工作,以撤消在工厂对象中执行的配置.
例如,使用Delete方法扩展工厂对象似乎是错误的,因为工厂模式是严格的创建模式.
更新:我使用工厂的原因是因为需要完成的配置会在对象中引入一些不适合的依赖项.将此解除配置放在构造函数中会产生同样的问题.
我已经看到了使用静态方法的Factory实现.像这样的东西:
public class MyFactory {
public static Product1 createProduct1() {}
public static Product2 createProduct2() {}
}
p1 = MyFactory.createProduct1();
p2 = MyFactory.createProduct2();
Run Code Online (Sandbox Code Playgroud)
我不确定我是否可以将其称为抽象工厂,但这不是问题.我对抽象工厂的理解是,它为我们提供了轻松更改产品系列的灵活性.
Factory factory = new MyFactory(); // might be a global or Singleton
p1 = factory.createProduct1();
p2 = factory.createProduct2();
Run Code Online (Sandbox Code Playgroud)
如果我想改变MyFactory,YourFactory那么只需要改变一行.我也可以在运行时更改它.但它们是否可以作为静态方法实现?我需要将所有调用更改为静态工厂.如果我们想在运行时决定,还需要在每个地方使用if-else检查.
p1 = YourFactory.createProduct1();
p2 = YourFactory.createProduct2();
Run Code Online (Sandbox Code Playgroud)
那么使用静态方法实现工厂的好处是什么?我们不是失去了主要的灵活性吗?我错过了什么?
请注意,不承担任何特定语言.任何帮助表示赞赏.
static design-patterns factory factory-pattern abstract-factory
我从这里的信息中匆匆忙忙:没有在子类中调用Metaclass
我的问题是我无法使用此类注册表创建对象的实例.如果我使用"常规"构造方法,那么它似乎正确地实例化对象; 但是当我尝试使用与注册表关联的类对象时,我得到一个错误,我传递的参数数量不正确.(似乎是调用元类new而不是我的构造函数...... ??)
我不清楚为什么它会失败,因为我认为我应该能够通过使用"callable"语法从类对象创建一个实例.
似乎我把这个元类放在注册表而不是类本身?但是我没有看到在新调用中访问类本身的简单方法.
这是我的代码示例,它无法实例化变量'd':
registry = [] # list of subclasses
class PluginMetaclass(type):
def __new__(cls, name, bases, attrs):
print(cls)
print(name)
registry.append((name, cls))
return super(PluginMetaclass, cls).__new__(cls, name, bases, attrs)
class Plugin(metaclass=PluginMetaclass):
def __init__(self, stuff):
self.stuff = stuff
# in your plugin modules
class SpamPlugin(Plugin):
def __init__(self, stuff):
self.stuff = stuff
class BaconPlugin(Plugin):
def __init__(self, stuff):
self.stuff = stuff
c = SpamPlugin(0)
b = BaconPlugin(0)
mycls = registry[1][1]
d = mycls(0)
谢谢你的帮助.
我正在为类模板寻找一个抽象工厂,其中类在静态初始化时自动注册.对于常规(非模板化)类,使用静态成员的解决方案非常简单.以下是一个(相当简单)解决方案的示例,它可以正常工作:
#include <cassert>
#include <iostream>
class Base {
public:
virtual size_t id() const = 0;
virtual const char* name() const = 0;
virtual ~Base() {}
};
typedef Base* (*CreateFunc)(void);
class SimpleFactory {
private:
static const size_t NELEM = 2;
static size_t id_;
static CreateFunc creators_[NELEM];
public:
static size_t registerFunc(CreateFunc creator) {
assert(id_ < NELEM);
assert(creator);
creators_[id_] = creator;
return id_++;
}
static Base* create(size_t id) { assert(id < NELEM); return (creators_[id])(); }
};
size_t SimpleFactory::id_ = 0;
CreateFunc SimpleFactory::creators_[NELEM];
class …Run Code Online (Sandbox Code Playgroud) 在听完清洁代码会谈之后,我开始明白我们应该使用工厂来组合对象.因此,例如,如果a House有a Door和a Door有a DoorKnob,则在HouseFactory我们创建new DoorKnob并将其传递给构造函数Door,然后将该新Door对象传递给构造函数House.
但是使用的类House (比如类名ABC)呢?这将取决于HouseFactory,对吗?那么我们传递HouseFactory构造函数ABC吗?我们不是必须以这种方式在构造函数中传递大量工厂吗?
目前我正在尝试使用Selenium和Proboscis编写自动化测试套件.我试图抽象webdriver并通过工厂模式实现.Page_object这里也创建了class,它在创建对象时将webdriver作为参数.下面是代码.
import selenium.webdriver as webdriver
from proboscis import TestProgram
from proboscis import test
from proboscis import before_class
from proboscis import after_class
class WebdriverFactory:
@staticmethod
def getWebdriver(browserName):
if(browserName == 'firefox'):
return webdriver.Firefox()
elif(browserName == 'chrome'):
return webdriver.Chrome()
elif(browserName == 'ie'):
return webdriver.Ie()
raise Exception("No such " + browserName + " browser exists")
class Page_Object:
def __init__(self, driver):
self.driver = driver
def go_to_home(self):
self.driver.get("http://google.com")
return self
def go_to_page(self,url):
self.driver.get(url)
return self
def run_search(self, url, query):
self.driver.get(url)
self.driver.find_element_by_id(locators['search_box']).send_keys(query)
self.driver.find_element_by_id(locators['search_button']).click()
def tear_down(self): …Run Code Online (Sandbox Code Playgroud) 我有以下课程:
我想基于url加载一个工厂(用于DI)的正确类:
现在我正试图避免为我的每一项服务创建一个工厂,我想以恐怖的方式做到这一点:
<?php namespace App\Service\Factory;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class ServiceFactory implements FactoryInterface
{
/**
* Create service
* @param ServiceLocatorInterface $serviceLocator
* @return \App\Service\AbstractService
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$servicename = ''; // how can I get something like this, based on the route ?
$service = $serviceLocator->get('Service\' . $servicename . 'Service');
}
}
Run Code Online (Sandbox Code Playgroud)
如果可能的话,我想避免计算工厂内的路线,因为如果有一天这个工厂将从其他地方调用,它将无法工作.
那么你如何基本上做一个工厂" 处理创建对象的问题而不用 zend 2 指定将要创建的对象的确切类 "?
编辑 - 使用解决方案
再次编辑,这里是我根据接受的答案首选的最终解决方案:
$apiName = str_replace(' …Run Code Online (Sandbox Code Playgroud) 我正在创建一些类来处理各种类型的文件共享(nfs,afp,s3,本地磁盘)等文件名.我得到一个用户输入一个标识数据源(即"nfs://192.168.1.3"或"s3://mybucket/data")等的字符串.
我从具有公共代码的基类继承特定文件系统.我困惑的地方是对象创建.我所拥有的是以下内容:
import os
class FileSystem(object):
class NoAccess(Exception):
pass
def __new__(cls,path):
if cls is FileSystem:
if path.upper().startswith('NFS://'):
return super(FileSystem,cls).__new__(Nfs)
else:
return super(FileSystem,cls).__new__(LocalDrive)
else:
return super(FileSystem,cls).__new__(cls,path)
def count_files(self):
raise NotImplementedError
class Nfs(FileSystem):
def __init__ (self,path):
pass
def count_files(self):
pass
class LocalDrive(FileSystem):
def __init__(self,path):
if not os.access(path, os.R_OK):
raise FileSystem.NoAccess('Cannot read directory')
self.path = path
def count_files(self):
return len([x for x in os.listdir(self.path) if os.path.isfile(os.path.join(self.path, x))])
data1 = FileSystem('nfs://192.168.1.18')
data2 = FileSystem('/var/log')
print type(data1)
print type(data2)
print data2.count_files() …Run Code Online (Sandbox Code Playgroud) 我创建了一个工厂和一组规范来创建和验证聚合根.目前我对工厂进行了一些测试,这些测试称工厂的产品规格,但我想知道这是否足够.从设计的角度来看,将工厂与其产品的规格相结合可能会更好,因为它们密切相关.
如果聚合根产品的规范用于验证而不是用于创建,那么从工厂内部调用它是否有意义?
或者单位测试是否足够好?
validation domain-driven-design aggregate specification-pattern factory-pattern
我知道有很多关于不同工厂模式的差异的问题,但答案是如此不同和令人困惑.我读过的书籍使用不清楚和(简化)简化的例子.即使在阅读维基百科的解释之后,我也有很多问题,以及关于它们的大量在线解释,包括所有这些网站上的解释.我正在阅读的这本书是Head First Design Patterns.
在Simple Factory中,客户端使用单独的类(Creator)和工厂方法(可以是静态的)来返回Products.
在工厂方法模式中,创建者和客户端是相同的东西,他们在同一个类中使用抽象方法来创建新的产品,它们在同一个类中运行.当然,造物主(或客户)是抽象的,因此关于制作混凝土产品的决定被推迟到子类.
我的理解是否正确(例如,FMP中的客户端和创建者是同一件事,我从未在FMP图中看到客户端)?
在Factory Method Pattern中,它表明create方法不能在Creator之外重用,所以它只能在创建一个新的Creator时重用?
在哪种情况下我可以选择一个而不是另一个?
(PS请不要将此标记为重复,我希望在此网站上明确这一点)