views:

306

answers:

4

I cant seem to grasp the proper concepts of a factory.

Can anyone help me code a simple test? I read some texts over the internet and cant code it the same way. Actually i cant understand the process. Copying code is easy, but i need to learn why this wont work.

class Factory:

    def __init__(self):
        self.msg = "teste"

    def fabricateAnotherObject(self,obj,**kwargs):
        return apply(obj,**kwargs)

class testClass:
    def __init__(self,nome,salario,endereco):
        self.nome = nome
        self.salario = salario
        self.endereco = endereco

    def __str__(self):
        return "Nome: " + str(self.nome) + "\nEndereco: " + str(self.endereco) + "\nSalario: " + str(self.salario) 

a = Factory()
emp = a.fabricateAnotherObject(testClass,"George",2000,"Three Four Five Avenue")
print str(emp)
A: 

Your fabricate method should look like this:

    def fabricateAnotherObject(self, obj, *args):
        return apply(obj, args)

apply() takes in a list of args. By taking in *args in your fabricateAnotherObject method, you consume all parameters beyond obj as a list that can be passed to apply().

Brent Newey
+11  A: 

Your code is counter-productive (sorry, I must say it).

The sense of a factory is, that you don't have to know the class of your constructed object at the position where you create it.

The reason is, that object creation creates a gap in object oriented abstraction. You must be concrete in creating the object. But sometimes you just want to create an object with some behaviour but somebody else should decide (centrally) what concrete class it is.

For example you must create one kind of object in 100 places. But later you might find out, that you must change the class -- you would have to change all those places.

The factory will eliminate this need by defining one place that you must change.

The simplest factory would be:

def fabricateAnotherObject(self, **kwargs):
    return testClass(**kwargs)

Of course, this might be of little help in some situations. So some factories might also load the class names from db or some other configuration. But the most simple solution is a hard-coded construction of the object -- only this method must be changed in our example, when you choose to always call this method.

A somewhat more dynamic solution (without need for a db):

class Factory(object):
   def __init__(self, theClass):
       self.theClass = theClass
   def create(self, **kwargs):
       self.theClass(**kwargs)

myFactory = Factory(testClass)

The myFactory instance can be used in different locations for creating the correct instances. The problem is, how to initialize myFactory -- in some special module??

Juergen
Of course in my constructed example, you don't need a factory class -- a simple factory function would suffice, as you can see that the self-param is not used.
Juergen
Juergen. That is exactly what i need. I must say thank your for your words. This here posted is just an example.
George
Oh just realized that the object is fixed. I kinda needed to be chosen dinamically. I will think of something. Thanks :D
George
I don't know, if I understand you right. You need more dynamic? This would also work. I will add it to the answer.
Juergen
Class objects are first-class citizens in Python. It means that you don't need to create a special factory you can just pass class object directly in exactly the same way as you pass an integer or string, for example.
J.F. Sebastian
@J.F.Sebastian: You are right. Sometimes you forget it, when in discussion. In some situations (e.g. reading customizing from db) a factory yet might make sense (of course in our simple examples here not).
Juergen
+2  A: 

Factory pattern is intended for programming languages that don't allow functions (and classes) as first-order values (such as C++ or Java).

The idea is that you pass an instance of a "factory" class as an argument to some function (or method or constructor), which is then used to produce new object instances (typically these are instances of some specific subclass of a superclass that is known in advance).

In Python, you can just pass the class instead (because classes (and functions) are also objects).

anonymous
A: 

See also type() in docs.python.org/library/functions:

type(name, bases, dict)

Return a new type object. This is essentially a dynamic form of the class statement. The name string is the class name and becomes the __name__ attribute; the bases tuple itemizes the base classes and becomes the __bases__ attribute; and the dict dictionary is the namespace containing definitions for class body and becomes the __dict__ attribute. For example, the following two statements create identical type objects:

class X(object):
    a = 1
X = type('X', (object,), dict(a=1))

For a short real program with one use of factories (compactly building lots of special dicts), see ofc2.py .
Experts, more examples please ?

Denis