Last Year's Shavuot-Themed OOP Final (2022)
Teaching at Stern College, I like to engage in Torah UMadda in many ways. One is making my exams Jewish-themed.
My Object Oriented Software Design final falls out around Shavuot. Here are some of the questions from last year:
Singleton Pattern.
At Har Sinai, the Israelites witnessed that in all of creation, Hashem was G_d, and there was no other. (We cannot use a dash since it is a minus sign, which separates identifiers; also, we don’t want to violate Bal Tigra, “thou shalt not subtract”. Therefore we use an underscore, and avoid turning this exam into sheimos.)We want to make a class called G_d, who can do things such as createUniverse(), restOnSeventh(), divinelyPronounce(), and performExodus(). However, in our code, we might make, in the same or separate threads, different references to this One entity. If we tried this:
then it feels like Avodah Zara (idolatry), as we’d be creating separate G_d entities.
Of course, all references must point to the same One entity. To do this, we need to make the class into a Singleton. Our code in main() would instead read:
Write the code for this Singleton class, in full.
Prototype Pattern
Moshe received the Torah on Har Sinai, it was faithfully transmitted to Yehoshua, to the Elders and so on. (See first Mishnah in Pirkei Avot.) Every time a Torah is written / transmitted, it isn’t written from scratch / from memory (with new), but copied / cloned from another Torah. Indeed, in the Temple Courtyard, there was a standard Torah used for reference. For this, we will employ the Prototype Pattern.
Write a Torah class which is the prototype, and a Transmitter Factory class which will produce a clone of the original Torah.Command Pattern / Lambda
On Har Sinai, Moshe received the 10 Commandments. The entire Torah consists of 613 commandments. Moshe can take these commandments from G_d and give them to the Israelites, who will execute() them, by obeying their parents and honoring the Shabbat day.
Write the Commandment interface.
Also, here is some code in main(): Fill in the blanks with some lambdas.Proxy Pattern
As the Israelites prepared for receiving the Torah, Hashem was concerned lest the people or beasts approach and touch the mountain (Har Sinai) or gaze during the giving of the Torah, and incur guilt. He told Moshe to set bounds, by instructing people not to approach. Only Moshe was allowed to ascend() the mountain. Anyone was allowed to listen().
Let us implement this using a Protection Proxy of the Mountain, so that Moshe is allowed full access and a typical Israelite is disallowed from doing so.
Write UML for all associated classes.
Write full code for the MountainProxy class, the Israelite class, and your Main class with a public static void main() connecting everything (including Moshe, Israelite, Mountain, and MountainProxy) and calling functions as appropriate.
Adapter Pattern
The G_d class has a divinelyPronounce() method which returns (doesn’t print) the text of the 10 Commandments. The Israelite class feels unable to directly communicate with G_d. They are able to interact with a HumanSpeaker abstract class (or interface), who has a pronounce() method that returns any string.To solve this problem, we will introduce a G_dAdapter, who will act as an intermediary, hearing from G_d and conveying the message to the Israelites.
Draw UML which encompasses all classes and their relationship to one another. Make sure to indicate what is a class, an interface, an abstract class, and has-a and is-a relationships. Alternatively, avoid UML and write all the code for all the classes except for what is in part (b).
Write the code for the G_dAdapter class, and driver code in your main() to show how it all works together.
Decorator Pattern
While the Biblical law is immutable, the Sages imposed decrees (gzeirot / takkanot), Talmudic rabbis had different interpretations, different medieval rabbis decided which way to rule , and different communities adopted their own customs (minhagim).
To simplify the above, we have Biblical as a concrete class, Rabbinic and Custom as abstract classes (with their own concrete classes), all which implement the Law interface or abstract class. To determine the ultimate way to act, at the basic level there is the Biblical law. But around that, there may be a Rabbinic Law. And around that, there may be a Custom.
In main(), we want to write code such as this:
Draw the UML for all of this, involving all abstract classes, interfaces, concrete classes, is-a and has-a relationships between them. Alternatively, avoid UML and write all the code for all the classes except for what is in part (b).
Write the code for the abstract Custom class and for the concrete ChassidicCustom class.
State Pattern
Prior to receiving the Torah, the Israelites had to purify themselves for three days. A pure Israelite and an impure Israelite can do different things. For instance, both of them can attempt to receiveTorah() but the impure one will throw an Exception. Both can touchFood(), but the impure one will render the food impure. Of course, they all can talk() in identical ways. You can turn an PureIsraelite into an ImpureIsraelite by contractingImpurity(), and back to a PureIsraelite e.g. by gettingSprinkled(). Your client code should be able to simply interact with an Israelite.
Draw UML which encompasses all classes and their relationship to one another. Make sure to indicate what is a class, an interface, an abstract class, and has-a and is-a relationships. No code alternatives on this question.
Write the full code for the Israelite class.
Iterator Pattern
From leaving Egypt, it was 49 days until the Israelites arrived at Har Sinai. Nowadays, we count these 49 days from Pesach to Shavuot.
You will use the Iterator pattern to carry this out, so that the following code will work, thereby printing the numbers 1 through 49 inclusive. Also, on day 33, there will be a side-effect of calling next() in which we will take a haircut and light a bonfire.
Cheesecake Factory
On Shavuot, it is traditional to consume copious amounts of cheesecake. There are different types of cheesecake. There is plain, blueberry, strawberry, and vegan.
Implement this using a Simple Factory, where the creational method takes in a String.
Implement this using the Factory Method pattern, where there is a process of creating, baking, cutting, and then eating a cheesecake. The factory method is the creational method. And use inheritance to make subclasses, in a way that avoids the if-elseif chains of part (a).
Concept questions (some based on your answers, some based on code we discussed)
If you answered question 1, what is the difference between lazy and eager implementations? Was the Singleton code that you wrote lazy or eager? Explain why.
If you answered a question which uses delegation, then what is delegation? In which question did you use delegation. Explain how exactly. What classes, methods were involved, and how this is delegation.
Why is it a bad idea to use design patterns? Refer to a design principle in your explanation.
If you answered question 6, which of your classes was equivalent to the CondimentDecorator? Explain why.
In class, I compared aspects of the decorator pattern to recursion. Explain how, and what the analogies are for the recursive and base case.
In class, I noted that the book’s code had every concrete condiment declared a reference to the next (abstract) Beverage it wrapped. What was my suggestion, and how would that possibly be better?
If you answered question 3, what is a SAM interface. How come, in your code, you were able to write lambdas for commandments?
If you answered question 7. How does the State pattern help us carry out the principle to “Prefer composition to inheritance?” Namely, explain what the equivalent would be for question 5 had you used inheritance instead. Also, how does the State pattern help us carry out the Open / Closed Principle? Explain using the book’s example.