我正在读Programming Perl,我找到了这段代码:
sub new {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
my $self = {
color => "bay",
legs => 4,
owner => undef,
@_, # Override previous attributes
};
return bless $self, $class;
}
Run Code Online (Sandbox Code Playgroud)
对于像这样的构造函数,调用new对象实例有什么好处?我认为这是它的用途,对吧?我的猜测是,如果有人想编写这样的构造函数,他将不得不添加一些代码,将第一个对象的属性复制到即将创建的对象.
当实现MessageFactory类来实例化Message对象时,我使用了类似的东西:
class MessageFactory
{
public:
static Message *create(int type)
{
switch(type) {
case PING_MSG:
return new PingMessage();
case PONG_MSG:
return new PongMessage();
....
}
}
Run Code Online (Sandbox Code Playgroud)
这工作正常但每次添加新消息时我都要添加一个新的XXX_MSG并修改switch语句.
经过一些研究后,我发现了一种在编译时动态更新MessageFactory的方法,因此我可以添加任意数量的消息,而无需修改MessageFactory本身.这样可以更简洁,更容易维护代码,因为我不需要修改三个不同的位置来添加/删除消息类:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
class Message
{
protected:
inline Message() {};
public:
inline virtual ~Message() { }
inline int getMessageType() const { return m_type; }
virtual void say() = 0;
protected:
uint16_t m_type;
};
template<int TYPE, typename IMPL>
class MessageTmpl: public Message
{
enum { _MESSAGE_ID = TYPE }; …Run Code Online (Sandbox Code Playgroud) 我已经越来越熟悉工厂模式(以及战略模式)以及模式可以带来的巨大好处.但是,我一直在努力应对以下情况:
以前,我会做类似以下的事情,其中有一个经理类可以构建和保存汽车.这里没有依赖注入,并且是一个糟糕的实现,特别是在尝试单元测试时.
public class CarManager
{
public static Car GetCarFromDatabase(int carId) { return new Car(); }
public static void SaveCar(Car car) { }
}
Run Code Online (Sandbox Code Playgroud)
我现在看到我可以Factories为我制造不同的车,无论是来自数据库,还是来自哪里!这很棒!所以,这是我的问题:
Q1:我的理解是,Factories只应构建对象,这是正确的吗?如果是这样,我的第二个问题呢?
Q2:如果我按照工厂模式构建我的对象,我应该如何保存我的对象?这有不同的模式,还是我不完全理解工厂模式?
c# design-patterns dependency-injection strategy-pattern factory-pattern
我有一个非常简单的工厂,需要一个枚举作为它的一个参数,以确定应创建的对象的类型,并正在创建的所有对象的共有的其他参数.
当我为工厂添加更多类型来创建我的对象时,构造函数的参数开始变化,例如:
public class someFactory {
public someFactory() {
}
public SomeObject newObject(Type type, Object data) {
return this.newObject(type, data, "");
}
public SomeObject newObject(Type type, Object data, Object stringOrObject) {
SomeObject someObject = null;
if (type != null) {
switch(type) {
case CREATE:
someObject = new CreateObject(data);
break;
case DELETE:
someObject = new DeleteObject(data, (String)stringOrObject);
break;
case EDIT:
someObject = new EditObject(data, (Object)stringOrObject);
break;
default:
break;
}
}
return someObject;
}
}
Run Code Online (Sandbox Code Playgroud)
我是不是应该使用工厂,只是使用正确的参数实例化不同的类型,或者可以以某种方式改进上述内容以使其更灵活?
是否真的不可能在jar文件中隐藏某些类?
我希望不允许直接实例化类以使其更灵活.这个罐子里只能看到工厂(或立面).
除了创建两个项目之外,还有其他办法解决这个问题吗?(两个项目:第一个包含类(实现),另一个引用第一个并包含工厂;后面只引用第二个)
我一直在审查Java Regex库,因为这个Pattern类没有我多年来认为理所当然的公共构造函数这一事实感到惊讶.
我怀疑使用静态compile方法支持构造函数的一个原因可能是构造函数总是返回一个新对象,而静态方法可能会返回先前创建的(和缓存的)对象,前提是模式字符串是相同的.
但是,如下所示,情况并非如此.
public class PatternCompiler {
public static void main(String[] args) {
Pattern first = Pattern.compile(".");
Pattern second = Pattern.compile(".");
if (first == second) {
System.out.println("The same object has been reused!");
} else {
System.out.println("Why not just use constructor?");
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用静态方法而不是构造函数的任何其他强有力的理由?
编辑:我在这里找到了一个相关的问题.那里的答案都没有说服我.通过阅读所有答案,我感觉静态方法相对于公共构造函数在创建对象方面具有相当多的优势,而不是相反.真的吗?如果是这样,我将为我的每个类创建这样的静态方法,并安全地假设它更具可读性和灵活性.
java constructor static-methods design-patterns factory-pattern
假设我有一项服务:
namespace Helloworld\Service;
class GreetingService
{
public function getGreeting()
{
if(date("H") <= 11)
return "Good morning, world!";
else if (date("H") > 11 && date("H") < 17)
return "Hello, world!";
else
return "Good evening, world!";
}
}
Run Code Online (Sandbox Code Playgroud)
我为它创建了一个invokable
public function getServiceConfig()
{
return array(
'invokables' => array(
'greetingService'
=> 'Helloworld\Service\GreetingService'
)
);
}
Run Code Online (Sandbox Code Playgroud)
然后在我的控制器中我能做到:
public function indexAction()
{
$greetingSrv = $this->getServiceLocator()
->get('greetingService');
return new ViewModel(
array('greeting' => $greetingSrv->getGreeting())
);
}
Run Code Online (Sandbox Code Playgroud)
据说这使得控制器依赖于服务(和ServiceManager)
更好的解决方案是为该服务创建工厂或在ServiceManager中返回一个闭包并在控制器中创建一个setter:
class IndexController extends AbstractActionController
{
private $greetingService;
public function …Run Code Online (Sandbox Code Playgroud) php service factory-pattern zend-framework2 service-management
这是我第一次Factory上课.下面是我的Factory类,我不确定这是否是制作线程安全的Singleton Factory类的正确方法.我将使用这个工厂返回我客户的实例?
public class ClientFactory {
private static ClientFactory instance = null;
private ClientFactory() {
}
public static ClientFactory getInstance() {
if (instance == null)
{
instance = new ClientFactory();
}
return instance;
}
public IClient getClient() {
return new TestClient();
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的TestClient类 -
public class TestClient implements IClient {
}
Run Code Online (Sandbox Code Playgroud)
这就是我将如何使用我的工厂 -
IClient client = ClientFactory.getInstance().getClient();
Run Code Online (Sandbox Code Playgroud) 我正在开展一个侧面项目,以更好地理解控制和依赖注入的反转以及不同的设计模式.
我想知道在工厂和战略模式中使用DI是否有最佳实践?
我的挑战来自于一个策略(从工厂构建)需要为每个可能的构造函数和实现提供不同的参数.结果,我发现自己在服务入口点声明了所有可能的接口,并将它们传递给应用程序.因此,必须针对新的和各种策略类实现更改入口点.
为了便于说明,我在下面汇总了一个配对示例.我的这个项目的堆栈是.NET 4.5/C#和Unity for IoC/DI.
在此示例应用程序中,我添加了一个默认的Program类,负责接受虚构的订单,并根据订单属性和所选的送货提供商计算运费.UPS,DHL和Fedex有不同的计算方法,每个实现可能依赖或不依赖于其他服务(访问数据库,api等).
public class Order
{
public string ShippingMethod { get; set; }
public int OrderTotal { get; set; }
public int OrderWeight { get; set; }
public int OrderZipCode { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
用于计算运费的虚拟计划或服务
public class Program
{
// register the interfaces with DI container in a separate config class (Unity in this case)
private readonly IShippingStrategyFactory _shippingStrategyFactory;
public Program(IShippingStrategyFactory shippingStrategyFactory)
{
_shippingStrategyFactory = shippingStrategyFactory;
}
public …Run Code Online (Sandbox Code Playgroud) c# design-patterns dependency-injection strategy-pattern factory-pattern
我正在为类模板寻找一个抽象工厂,其中类在静态初始化时自动注册.对于常规(非模板化)类,使用静态成员的解决方案非常简单.以下是一个(相当简单)解决方案的示例,它可以正常工作:
#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)