我对工厂的理解是它封装了所有继承公共抽象类或接口的具体类的实例化.这允许客户端与确定要创建哪个具体类的过程分离,这反过来意味着您可以从程序中添加或删除具体类,而无需更改客户端的代码.你可能不得不改变工厂,但工厂是"专门建造的",实际上只有一个改变的理由 - 添加/删除了一个具体的类.
我已经构建了一些实际上封装了对象实例化的类,但原因不同:对象很难实例化.目前,我将这些类称为"工厂",但我担心这可能是一种误称,并会混淆其他可能会查看我的代码的程序员.我的"工厂"类没有决定实例化哪个具体类,它们保证一系列对象将以正确的顺序实例化,并且当我调用时,正确的类将被传递给正确的构造函数new().
例如,对于我正在处理的MVVM项目,我编写了一个类来确保我SetupView的实例化得当.它看起来像这样:
public class SetupViewFactory
{
public SetupView CreateView(DatabaseModel databaseModel, SettingsModel settingsModel, ViewUtilities viewUtilities)
{
var setupViewModel = new SetupViewModel(databaseModel, settingsModel, viewUtilities);
var setupView = new SetupView();
setupView.DataContext = setupViewModel;
return setupView;
}
}
Run Code Online (Sandbox Code Playgroud)
把它称为"工厂"是否令人困惑?它不决定几个可能的具体类,它的返回类型不是接口或抽象类型,但它确实封装了对象实例化.
如果它不是"工厂",它是什么?
编辑
很多人都认为这实际上是Builder Pattern.
从dofactory定义Builder Pattern 如下:
将复杂对象的构造与其表示分开,以便相同的构造过程可以创建不同的表示.
这似乎也有点延伸.困扰我的是"不同的表现形式".我的目的不是抽象构建视图的过程(不是那个不值得的目标).我只是想在一个地方设置创建特定视图的逻辑,这样如果任何成分或创建该视图的过程发生变化,我只需要更改这一个类.构建器模式似乎真的在说,"让我们创建一个创建视图的一般过程,然后您可以为您创建的任何视图执行相同的基本过程." 很好,但那不是我在这里做的.
编辑2
我刚刚在维基百科关于依赖注入的文章中找到了一个有趣的例子.
在"Manually Injected依赖"下,它包含以下类:
public class CarFactory {
public static Car buildCar() {
return new Car(new SimpleEngine());
}
}
Run Code Online (Sandbox Code Playgroud)
这几乎是完全相同 …
我正在思考在PHP中实现工厂模式的两种不同方法之一.我不知道这些变种是否有正确的名称,所以现在我打算称它们为内部工厂和外部工厂.
内部工厂:工厂方法在类本身中实现为静态公共方法
<?php
class Foo
{
protected
$loadedProps = false;
public static factory ($id)
{
$class = get_called_class ();
$item = new $class ($id);
if ($item -> loadedProps ())
{
return ($item);
}
}
public function loadedProps ()
{
return ($this -> loadedProps);
}
protected function loadPropsFromDB ($id)
{
// Some SQL logic goes here
}
protected function __construct ($id)
{
$this -> loadedProps = $this -> loadPropsFromDB ($id);
}
}
?>
Run Code Online (Sandbox Code Playgroud)
外部工厂:工厂及其初始化的项目作为单独的实体实施
<?php
class Foo
{
protected
$loadedProps = …Run Code Online (Sandbox Code Playgroud) 使用enum或String分派到正确的对象以在static工厂方法中创建更好吗?
示例String:
public static Car createCar(String carName){
if(carName.equals("Ferrari")){
return new Ferrari();
}
else if(carName.equals("Porsche")){
return new Porsche();
}
....
}
Run Code Online (Sandbox Code Playgroud)
示例enum:
public static Car createCar(CarEnum carEnum){
if(CarEnum.FERRARI.equals(carEnum)){
return new Ferrari();
}
else if(CarEnum.PORSCHE.equals(carEnum)){
return new Porsche();
}
....
}
Run Code Online (Sandbox Code Playgroud)
目前,据我所知:
使用的好处enum:
carName.使用的缺点Enum:
增加依赖项,因为更改为enum(例如FERRARI变成ENZO_FERRARI)将需要在客户端上进行修改。但是,String我们可以Ferrari在Enzo Ferrari不重新编译客户端代码的情况下重定向到实例。当然,我们可以使用enum重定向FERRARI到的旧值为客户端做同样的事情,ENZO-FERRARI enum但对我来说,这意味着 …
考虑一下 interface
public interface IDoSomething {
void DoAAA();
void DoBBB();
void DoCCC();
}
Run Code Online (Sandbox Code Playgroud)
和这两个实现
public class MyObject1 implements IDoSomething {
public MyObject(int a, xObjx x)
..
}
public class MyObject2 implements IDoSomething {
public MyObject(int a, xObjx x)
..
}
Run Code Online (Sandbox Code Playgroud)
我怎么能不将实现类暴露给其他开发人员?具体如何防止以下情况?
IDoSomething C = new MyObject2();
Run Code Online (Sandbox Code Playgroud)
使用工厂级的最佳做法是什么?
public class DoSomethingFactory {
static IDoSomething getDoSomething(int a, xObjx x) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
如何扩展此模式以包含具有不同构造函数的实现?
我正在尝试(我认为)一个工厂,它根据传递给方法的枚举创建一个存储库.看起来像这样:
RepositoryFactory
public class RepositoryFactory
{
public IRepository<IEntity> GetRepository(FormTypes formType)
{
// Represents the IRepository that should be created, based on the form type passed
var typeToCreate = formType.GetAttribute<EnumTypeAttribute>().Type;
// return an instance of the form type repository
IRepository<IEntity> type = Activator.CreateInstance(typeToCreate) as IRepository<IEntity>;
if (type != null)
return type;
throw new ArgumentException(string.Format("No repository found for {0}", nameof(formType)));
}
}
Run Code Online (Sandbox Code Playgroud)
IRepository
public interface IRepository <T>
where T : class, IEntity
{
bool Create(IEnumerable<T> entities);
IEnumerable<T> Read();
bool Update(IEnumerable<T> entities);
bool …Run Code Online (Sandbox Code Playgroud) 我正在使用以下(简化的)工厂设计来创建一些继承层次结构的对象,不应该是任何特殊的:
// class to create
class Class
{
public:
Class(Type type, Foo foo);
};
// Simple creator class.
// Used in practice to do some runtime checks about whether or not construction is allowed.
class Creator
{
public:
Class* create( Type type, Foo foo ) const
{
return new Class( type, foo );
}
};
class Factory
{
public:
Factory
{
// fill object creator map on construction
_map[ "name" ] = new Creator<Class>;
}
Class* create( const std::string& name, …Run Code Online (Sandbox Code Playgroud) 从Effective Java的第4章开始,给出了以下示例:
public class Complex {
private final double re;
private final double im;
private Complex(double re, double im) {
this.re = re;
this.im = im;
}
public static Complex valueOf(double re, double im) {
return new Complex(re, im);
}
... // Remainder unchanged
}
Run Code Online (Sandbox Code Playgroud)
[...]它是最灵活的,因为它允许使用多个包私有实现类.对于位于其包之外的客户端,不可变类实际上是最终的,因为不可能扩展来自另一个包并且缺少公共或受保护构造函数的类.
我明白班级是有效的final,
但是没有宣布它有什么实际优势final吗?
当类不支持扩展时省略此关键字似乎是一种不太清楚的方式来传达如何API使用它.或者final只是留在这里向读者展示不可扩展的非最终类是可能的?
从上周开始,我在Azure数据工厂(v2)中运行的SSIS包逐个失败。他们没有改变。所有软件包都因相同的一系列错误而失败,如下所示。
这些程序包可以在Visual Studio中完美运行,但是当我将它们部署到Data Factory时,我收到了这些消息。
关于如何看待有什么想法?
我试图重新编译脚本组件,以重新部署整个项目。我还尝试将C#代码复制到新组件中,不幸的是导致了同样的问题。
我正在寻找一个我正在研究的项目的设计模式,并想知道我是否可以得到一些输入.
背景
名为Ranker的接口定义如下.
interface Ranker<T> {
public void rank(List<T> item);
}
Run Code Online (Sandbox Code Playgroud)
Ranker的每个实现都可以有多个Rankers作为成员变量,每个成员Rankers都可以有多个Rankers作为其成员变量.你明白了.排名者可以使用其他排名来帮助排名它的项目.
在我的特定情况下,我有27个不同的Rankers,每个Rankers都定义了不同的 dataType.其中一个Rankers将使用其中26个最终能够对这些项目进行排名.
RankerForTypeA
RaknerForTypeB
RankerForTypeC
RankerForTypeD
RankerForTypeE
RankerForTypeF
RankerForTypeG
RankerForTypeH
RankerForTypeI
RankerForTypeJ
RankerForTypeK
...
Run Code Online (Sandbox Code Playgroud)
意思是,RankerTypeA具有RankerTypeB,RankerTypeF和RankerTypeK作为成员并且需要它们以便适当地对A类项进行排序.
问题
每个Rankers的实例化逻辑都不同.我想使用一些帮助我创建这些助手的模块/工厂/等.我最终需要它来创建RankerForTypeA.我有类似的想法.
interface RankerFactory {
Ranker<A> getRankerForA(paramsForA);
Ranker<B> getRankerForB(paramsForB);
Ranker<C> getRankerForC(paramsForC);
...
}
public class DefaultRankerFactory implements RankerFactory {
Ranker<A> getRankerForA(paramsForA) {
getRankerForB(paramsForB)
...
}
Ranker<B> getRankerForB(paramsForB) {
getRankerForC(paramsForC)
...
}
Ranker<C> getRankerForC(paramsForC) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
这有点棘手.我想让人们轻松地说使用他们认为合适的定制助手.回到我之前绘制的层次结构,让我们说对于TypeB,人们想要使用CustomRankerForTypeB而不是 …
我的目标是根据枚举返回一个方法.目前,我已经创建了一个工厂,但它使用的是我不喜欢的开关盒.代码工作正常但我想使用更好的模式并替换当前的开关案例.你如何设计这个没有任何开关案例或如果否则(实例)......
我还试图在枚举中实现一个Stategy模式.但是无法自动装配bean.
请参阅下面的我目前的代码.
public enum Car {
AUDI, FORD;
}
Run Code Online (Sandbox Code Playgroud)
public class SuperCar{
private Car car;
}
Run Code Online (Sandbox Code Playgroud)
public class Audi extends SuperCar{
// some other properties
}
Run Code Online (Sandbox Code Playgroud)
public class Ford extends SuperCar{
// some other properties
}
Run Code Online (Sandbox Code Playgroud)
@Service
public class AudiService{
public void save(Audi audi){
// some code
}
}
Run Code Online (Sandbox Code Playgroud)
@Service
public class FordService{
public void save(Ford ford){
// some code
}
}
Run Code Online (Sandbox Code Playgroud)
@Service
public class CarFactory{
private FordService fordService;
private AudiService audiService;
public CarFactory(FordService fordService, AudiService audiService) {
this.fordService …Run Code Online (Sandbox Code Playgroud)