Maybe it's my Java background coming through, but I like the idea of Factory constructors.
Maybe it's my Java background coming through, but I like the idea of Factory constructors.
http://discuss.joelonsoftware.com/default.asp?joel.3.219431
NB Factories are one of these things that seem like a good idea in theory, but often seem to end up with crazy levels of abstraction in practice.
"New layers, more layers, bigger layers, better layers, abstract layers, injected layers, factory layers, module layers, AbstractFactoryFactoryModuleBuilderInjector layers, layers upon layers within layers wrapped in layers, a glorious spire of layers to reach the heavens and bring renown to Babylon! Hellelujah!"
Essentially closures, curried functions, partial evaluated is the same thing: code that generate code.
I'm not a java developer
That doesn't make factories bad.
Better languages don't special-case the constructor instead (no `new` operator), the constructor is just a class method. Bam, "factory method" constructors out of the box and problem solved.
Does Python do that too?
Factories aren't common in Python, but they are used in exactly the same cases where they are used in Java (eg [1],[2],[3]). If you need to decide at runtime what object from an object hierarchy to create you use a factory. There's nothing inherently bad about that.
[1] http://www.linuxtopia.org/online_books/programming_books/pyt...
[2] http://stackoverflow.com/questions/8129018/factory-method-in...
[3] http://eikke.com/python-factory-like-type-instances/ (though I prefer the version in the comments here)
Factories are everywhere in Python because the default construction workflow goes through a bloody factory method.
> There's nothing inherently bad about that.
You may want to read my comment instead of inventing things I never wrote, because the comment you replied to didn't even remotely hint at factories being bad.
Oh, and the first two examples you provide are absolutely horrendous, it's not surprising they are used "in exactly the same cases where they are used in Java", because what you show there really is java code translated to Python.
Whereas the third one is something you can't do in Java: it factorizes the creation of a class through customization of the metaclass's standard creation protocol. The version in the comments overrides the creation of the instance (through, again, a completely standard override of Python's built in construction protocol), which is less efficient but doesn't require understanding metaobjects.
DI Frameworks were originally created to provide an alternative to Factories.
A classical, say Java or C# way will still need coupling to such a class. In dart, there is real decoupling going on.
Uh no it does not, it just needs a class. Unless what you mean by "a class instance" is "a class object". A factory method is a classmethod, not an instancemethod.
A factory method and a "factory constructor" need exactly the same thing: the class object.
> In dart, there is real decoupling going on.
In dart, there's mostly a bloody mess of 4 different constructors when all you need is a constructor and an initializer, as done in e.g. Ruby or Python. And these can be "regular" methods (respectively on the class and on the instance).
Conversely, you can also have an "overridden" constructor as in Javascript: an instance is built, the constructor function is called using the instance as its context, and if the constructor returns something that something is returned by `new` in stead of the original object.
This completely depends on your implementation. It's possible to implement it as instance method, or static method.
> Uh no it does not, it just needs a class.
Whether it be a static factory method or an instance method, fact is you need a reference to an implementation (class). In dart, you can do
List someListInstance = new List();
where List is an interface. There is none class needed in your consuming code, none. In C# or Java, this is impossible: You need _some_ class (whether it be a static method on it, or an instance method) to get a new instance of the interface.Named constructors felt very liberating when working with Dart.
new List.from([instance1, instance1]);
delivers a lot of clarity, while offering the promised decoupling by the GoF:> Define an interface for creating an object, but let the classes which implement the interface decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.
(I don't know Dart, though)
It makes no sense, if you're doing that you've switched to full-blown factories (abstracts or builders), you're not using factory methods anymore.
> Whether it be a static factory method or an instance method, fact is you need a reference to an implementation (class). In dart, you can do
> List someListInstance = new List();
> where List is an interface. There is none class needed in your consuming code, none.
That's got nothing to do with factories, or interfaces.
> You need _some_ class (whether it be a static method on it, or an instance method) to get a new instance of the interface.
You always need a class, even in Dart there has to be a default List implementation of some sort which can be called (and has to be specified on the interface, it's not like you can even provide your own default implementation of a third party's interface). As to the calling code needing to know about that one concrete implementation:
abstract class Foo {
public static Foo foo() {
return new FooImpl();
}
public abstract void printFoo();
}
class FooImpl extends Foo {
public void printFoo() {
System.out.println("I am FooImpl");
}
}
class Main {
public static void main(String[] args) {
Foo foo = Foo.foo();
foo.printFoo();
}
}
Oh look at that, the calling code does not know anything about FooImpl.> Named constructors felt very liberating when working with Dart.
Yeah, that's so much more liberating than:
List.from([instance1, instance2]);
Wait, no it's not.> You always need a class
Nope. That's the whole point which I am trying to communicate: you do not need a reference to a class to get the instance of the interface from, as you confirm later on:
> As to the calling code needing to know about that one concrete implementation:
My personal feeling of liberation comes from the fact that the code is simpler and more clear. The non-coupling is nice, but can be achieved with dependency injection too: the point is the transfer of characters into a mental model which is more efficient with the named constructors/factory constructors.
Foo is an abstract class, which is the exact same thing.
> Nope. That's the whole point which I am trying to communicate: you do not need a reference to a class to get the instance of the interface from
Neither do you in the code I posted, can you bloody read?
> My personal feeling of liberation comes from the fact that the code is simpler and more clear.
You'll have to give actual examples of that, because I've not seen it so far.
> the point is the transfer of characters into a mental model which is more efficient with the named constructors/factory constructors.
This phrase doesn't even make sense, what "transfer of characters" are you talking about, and how is it more efficient for the user to type more? (named constructors only add ceremony to factory methods) (I'm not even going to talk about factory constructors again, they're a band-aid on the self-inflicted wound of stupid java-style constructors)
To whit: let's say you want to have an interface for associative arrays. Let's call it Map. Now let's say you want to provide a static method to create an instance of the default Map implementation (call it, say, HashMap). So you'd think about doing something like this:
interface Map { ... static defaultImpl() { .... } }
Except, interfaces can't have implementation in them. That would imply multiple inheritance (which languages like Dart and Java don't support).
Okay, so one workaround: use an abstract class:
abstract class Map { ... static defaultImpl() { .... } }
The only problem is that if you define Map as an abstract class instead of an interface, that means that all implementations of Map must extend Map. Given single inheritance, this means anything providing a Map-style interface can and must only extend from the base Map class.
So... Factory classes are there because of how Java treats interfaces and single inheritance.