我对工厂的理解是它封装了所有继承公共抽象类或接口的具体类的实例化.这允许客户端与确定要创建哪个具体类的过程分离,这反过来意味着您可以从程序中添加或删除具体类,而无需更改客户端的代码.你可能不得不改变工厂,但工厂是"专门建造的",实际上只有一个改变的理由 - 添加/删除了一个具体的类.
我已经构建了一些实际上封装了对象实例化的类,但原因不同:对象很难实例化.目前,我将这些类称为"工厂",但我担心这可能是一种误称,并会混淆其他可能会查看我的代码的程序员.我的"工厂"类没有决定实例化哪个具体类,它们保证一系列对象将以正确的顺序实例化,并且当我调用时,正确的类将被传递给正确的构造函数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)
这几乎是完全相同 …
也许这是一个简单的 C# 新手问题,但就这样吧 — 这将是我与其他问题的一次全新突破,这些问题非常困难,以至于没有人知道答案。:)
假设我有一个 C# 泛型类型:
Thing<T>
Run Code Online (Sandbox Code Playgroud)
假设我想使用静态工厂方法来制作一个东西。在 Java 中,这没有问题:
public static <T> Thing<T> createThing()
{
return flag ? new Thing<Integer>(5) : new Thing<String>("hello");
}
Run Code Online (Sandbox Code Playgroud)
我如何在 C# 中执行此操作?谢谢。
我正在思考在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) 考虑一下 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)
如何扩展此模式以包含具有不同构造函数的实现?
我想要一个类,它根据我传递的字符串创建不同类型的对象。根据我的研究,这最好地描述了工厂设计模式。我成功地实现了它,但遇到了一个设计问题:我不知道如何创建具有不同长度构造函数的对象。
我们以一个名为 Pet 的抽象父类为例。其中有 3 个孩子:鱼、猫和狗。它们都继承了 Pet 的重量和颜色,因此它们都包含在它们的构造函数中。但是一条鱼可能需要多个鳍和一个关于它是否是咸水鱼的布尔值。这是一个 4 参数构造函数。猫想要腿的数量。那是3个参数。狗可能有腿、品种以及是否与其他狗相处良好等 5 个参数。
在 C++ 中,我知道没有任何反射,因此最常见的做法似乎只是声明一个字符串到函数指针的映射,其中函数指针指向一个如下所示的函数:
template<typename T> Pet* createObject(int weight, std::string color) {return new T(weight, color);}
Run Code Online (Sandbox Code Playgroud)
同样,我不确定如何在调用中填充更多参数而不影响其他对象构造函数的调用。
我可以想到两种解决方法:创建新函数来接受不同数量的参数,或者为构造函数创建超过一定大小的默认参数。
解决方法 1 似乎有点过多,具体取决于我有多少个不同的参数大小。
解决方法 2 似乎忽略了构造函数的全部要点,因为我将被迫在调用构造函数后分配数据。
还有其他更好的解决方法吗?
我正在尝试(我认为)一个工厂,它根据传递给方法的枚举创建一个存储库.看起来像这样:
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) 从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)