Name: Anonymous 2012-10-17 6:06
Amazing programming explanation using examples which respect people of all genders! I think everyone engaged in IT discussion and teaching should follow this style of highly tolerant and privilege-aware writing. ``Transgender'' and ``homosexual'' should become new ``foo'' and ``bar'' in educational code snippets.
---
I'll take a crack at the Factory Method pattern:
The Factory Method pattern uses a single method to construct objects according to some run-time data rather than hardcoding with new. For example, you may have a program which in various places may need to create a MalePerson or FemalePerson object depending on input, so you'd naturally pepper your code with:
Now what if you need to handle instances of TransgenderPerson or UndeclaredGenderPerson, etc? You'll have to go back and add those conditions to each place that conditional object creation occurs.
So, instead we employ the Factory Method pattern to be able to just call
This encapsulates all creation of objects based on run-time data behind a single interface.
In Java this might be implemented as
The declaration of the corresponding classes in Common Lisp is pretty straight forward:
But, in Common Lisp, methods do not belong to classes, but to generic functions which dispatch specific methods based on their arguments. There is even EQL specialization on methods, which allows for methods to be dispatched based on the equality of their arguments to a specified value. So our PersonFactory in Common Lisp would look like:
You'll notice that Common Lisp lacks a new operator. That's because there are no "constructors" in the usual sense of the word. The standard way of creating objects is to pass runtime data either a class object or symbol that is the name of the class object to the factory method MAKE-INSTANCE.
Now, that's all well and good, but let's look at what happens when we want to add the feature to create a TransgenderPerson to our factories. In Java we have to open the PersonFactory.java class file and modify it:
But in Common Lisp, we do not need to modify anything. We can just extend the MAKE-PERSON generic function with a new method:
---
I'll take a crack at the Factory Method pattern:
The Factory Method pattern uses a single method to construct objects according to some run-time data rather than hardcoding with new. For example, you may have a program which in various places may need to create a MalePerson or FemalePerson object depending on input, so you'd naturally pepper your code with:
if (gender.equalsIgnoreCase("male")) {
return new MalePerson(name);
} else {
return new FemalePerson(name);
}Now what if you need to handle instances of TransgenderPerson or UndeclaredGenderPerson, etc? You'll have to go back and add those conditions to each place that conditional object creation occurs.
So, instead we employ the Factory Method pattern to be able to just call
PersonFactory.makePerson("male");This encapsulates all creation of objects based on run-time data behind a single interface.
In Java this might be implemented as
public abstract class Person {
protected final String name;
public Person(String name) {
this.name = name;
}
}
public class MalePerson extends Person {
public MalePerson(String name) {
super(name);
}
}
public class FemalePerson extends Person {
public FemalePerson(String name) {
super(name);
}
}
public class PersonFactory {
public static Person makePerson(String gender, String name) {
if (gender.equalsIgnoreCase("male")) {
return new MalePerson(name);
} else {
return new FemalePerson(name);
}
}
}The declaration of the corresponding classes in Common Lisp is pretty straight forward:
(defclass person ()
((name :initarg :name :reader name)))
(defclass female-person (person)
())
(defclass male-person (person)
())But, in Common Lisp, methods do not belong to classes, but to generic functions which dispatch specific methods based on their arguments. There is even EQL specialization on methods, which allows for methods to be dispatched based on the equality of their arguments to a specified value. So our PersonFactory in Common Lisp would look like:
(defgeneric make-person (gender name))
(defmethod make-person ((gender (eql 'male)) name)
(make-instance 'male-person :name name))
(defmethod make-person ((gender (eql 'female)) name)
(make-instance 'female-person :name name))You'll notice that Common Lisp lacks a new operator. That's because there are no "constructors" in the usual sense of the word. The standard way of creating objects is to pass runtime data either a class object or symbol that is the name of the class object to the factory method MAKE-INSTANCE.
Now, that's all well and good, but let's look at what happens when we want to add the feature to create a TransgenderPerson to our factories. In Java we have to open the PersonFactory.java class file and modify it:
public class PersonFactory {
public static Person makePerson(String gender, String name) {
if (gender.equalsIgnoreCase("male")) {
return new MalePerson(name);
} else if (gender.equalsIgnoreCase("transgender")) {
return new TransgenderPerson(name);
} else {
return new FemalePerson(name);
}
}
}But in Common Lisp, we do not need to modify anything. We can just extend the MAKE-PERSON generic function with a new method:
(defmethod make-person ((gender (eql 'transgender)) name)
(make-instance 'transgender-person :name name))