Pattern Discussions

Factory

Abstract Factory

Prototype

Singleton

Composite

Decorator

Flyweight

Proxy

Facade

Adapter

Strategy

Template method

Command

Chain of Responsibility

Memento

Mediator

State

Observer

Visitor

 

 

Factory Method

How does this promote loosely coupled code?

Answer

The abstraction that Factory Method brings to decide which of the possible classes to return depending on the data provided to it keeps the data dependence separated from the classes’ useful methods. In addition, the user only needs to be aware of the interface or methods of the base class, which also provides some level of indirection.

With these, factory method promotes loosely coupled code because users do not need to rewrite or change the methods according to the change of data provided to a class. It simply requires changing or adding the derived classes pertinent to the change of data provided to the class.

 

 

Abstract Factory

1) In the Implementation section of this pattern, the authors discuss the idea of defining extensible factories. Since an Abstract Factory is composed of Factory Methods, and each Factory Method has only one signature, does this mean that the Factory Method can only create an object in one way?

Answer

Adding a new kind of product requires changing the Abstract Factory interface and all the classes that depend on it.  Nevertheless, we may add a new kind of product by adding a parameter to operations that create object. The parameter specifies the kind of the object to be created. This approach is more flexible but less safe than changing the Abstract Factory interface and all the classes that depend on it. However, it only needs a single operation with a parameter indicating the kind of object to create.

Abstract Factory

2) Consider the MazeFactory example. The MazeFactory contains a method called MakeRoom, which takes as a parameter one integer, representing a room number. What happens if you would also like to specify the room's color & size? Would this mean that you would need to create a new Factory Method for your MazeFactory, allowing you to pass in room number, color and size to a second MakeRoom method?

Answer

We may create a new Factory Method to pass in room number, color and size to a second MakeRoom method. But we can add set method to specify the room’s color and size after the object room is created or overload MakeRoom method with those additional parameters.

Abstract Factory

3) Of course, nothing would prevent you from setting the color and size of the Room object after is has been instantiated, but this could also clutter your code, especially if you are creating and configuring many objects. How could you retain the MazeFactory and keep only one MakeRoom method but also accommodate different numbers of parameters used by MakeRoom to both create and configure Room objects?

Answer

Overloading MakeRoom method can be one way to keep only one method and accommodate different number of parameters though it may introduce some ambiguities for the user to use it.

 

 

Builder

Like the Abstract Factory pattern, the Builder pattern requires that you define an interface, which will be used by clients to create complex objects in pieces. In the MazeBuilder example, there are BuildMaze(), BuildRoom() and BuildDoor() methods, along with a GetMaze() method. How does the Builder pattern allow one to add new methods to the Builder's interface, without having to change each and every sub-class of the Builder?

Answer

We may provide a default implementation of the new method that we would like to add to the Builder’s interface so that all the subclass of the Builder inherits the method and use it. Then the method must be defined as concrete in the Builder class. However, if one would like to have the newly added method to have specific algorithm for each subclass, then every subclass has to be changed.

 

 

Prototype

1) When should this creational pattern be used over the other creational patterns?

Answer

§         When a system should be independent of how its products are created, composed, and represented

§         When the classes to instantiate are specified at run-time, for example, by dynamic loading

§         To avoid building a class hierarchy of factories that parallels the class hierarchy of products

§         When instances of a class can have one of only a few different combinations of state. It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually, each time with the appropriate state. I.e. whenever you need classes that differ only in the type of processing they offer 

§         When creating an instance of a class is very time consuming or complex in some way

Prototype

2) Explain the difference between deep vs. shallow copy.

Answer

The difference between shallow and deep copying is only relevant for compound objects such as objects that contain other objects, lists or class instances.

A shallow copy constructs a new compound object and then to the extent possible inserts references into it to the objects found in the original.

A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

 

 

Singleton

The Singleton pattern is often paired with the Abstract Factory pattern. What other creational or non-creational patterns would you use with the Singleton pattern?

Answer

For creational pattern, it could be used with Builder and Prototype. The internal components that consist of the object could be Singleton with Builder and Prototype object that is cloned could be Singleton.

For non-creational pattern, Façade may be used with Singleton pattern in case one single instance of interface to a set of interfaces in the subsystem is needed. Mediator or Proxy can be also paired with Singleton in the same sense.

 

 

Composite

1) How does the Composite pattern help to consolidate system-wide conditional logic?

Answer

Composite pattern enables the client treat both individual objects and compositions of object uniformly by defining an abstract component class. A client can access those individual objects and compositions of objects without knowing whether the object is a leaf or composite. It allows the same conditional logic to be used to handle both in system wide manner.

Composite

(ii) Would you use the composite pattern if you did not have a part-whole hierarchy? In other words, if only a few objects have children and almost everything else in your collection is a leaf (a leaf that has no children), would you still use the composite pattern to model these objects?

Answer

It depends on whether we need to have a common interface to both individual objects and composition of objects. If it is, composite pattern can be useful to model those objects. In case that most leaf nodes(individual objects) have some common operation, defining that operation in a component is also good to provide common interface.

 

 

Observer

1) The classic Model-View-Controller design is explained in Implementation note #8: Encapsulating complex update semantics. Would it ever make sense for an Observer (or View) to talk directly to the Subject (or Model)?

Answer

The controller ensures that all observers are notified only once after all subjects have gone through changes to avoid unnecessary updates of observers in the implementation note. If an observer needs to reflect the change of the subject without delay or immediately, then it would make sense for an observer to talk directly to the Subject. However, this could make the design unclear and difficult to follow when there are many observers that the controller does not regulate their interaction with subject (model).

Observer

2) What are the properties of a system that uses the Observer pattern extensively? How would you approach the task of debugging code in such a system?

Answer

When a system uses the Observer pattern extensively, it can be roughly divided into observer and subject part. There would be many communications between them and it could be very tricky to keep track of to which observers the state change of which subjects notifies. It may cause debugging the code difficult due to dependencies between objects.

Classifying the communications between subjects and observers could help debugging the code in such a system. Because we know what subject causes the change in the observer, we can check that the change in the observer states is done correctly and consistent with the change of the subject.

Observer

3) Is it clear to you how you would handle concurrency problems with is pattern? Consider an Unregister() message being sent to a subject, just before the subject sends a Notify() message to the ChangeManager (or Controller).

Answer

We can use timestamp on the Notify() message from a subject to Controller in the order that the subject send.  Then the Controller keeps the messages from the last consistent state between the subject and observer in the buffer, updates the observer and checks the states of both observer and subject.

 

 

Proxy

If a Proxy is used to instantiate an object only when it is absolutely needed, does the Proxy simplify code?

Answer

The Proxy pattern introduces a level of indirection when accessing an object.  It does not necessarily mean that Proxy simplifies code because the real subject of proxy has to be implemented though its instantiation can be deferred until it is necessary.  Moreover, we have to consider some issues such as how the real subject must be replaced by the proxy object and how to control access to the real object in implementation. On the other hand, proxy can simplify the code in that the remote proxy hides the fact that an object resides in a different space and both protection proxies and smart reference allow additional housekeeping tasks when an object is accessed because we do not need to take care of those restrictions in the real subject code.

 

 

Strategy

1) What happens when a system has an explosion of strategy objects? Is there some better way to manage these strategies?

Answer

In case of several contexts using different instance of the same strategy, we can use flyweight pattern to reduce the overhead. In other words, we can implement strategy as stateless objects that those contexts can share and any residual state is maintained by the context, which passes it in each request to the strategy object. Shared strategies should not maintain state across invocations.

Strategy

2) In the implementation section of this pattern, the authors describe two ways in which a strategy can get the information it needs to do its job. One way describes how a strategy object could get passed a reference to the context object, thereby giving it access to context data. But is it possible that the data required by the strategy will not be available from the context's interface? How could you remedy this potential problem?

Answer

One approach is to pass all the data that the strategy has to access into the strategy object, which decouples the strategy object from the context. 

 

 

Decorator

In the Implementation section of the Decorator Pattern, the authors write: A decorator object's interface must conform to the interface of the component it decorates.

Now consider an object A that is decorated with an object B. Since object B "decorates" object A, object B shares an interface with object A. If some client is then passed an instance of this decorated object, and that method attempts to call a method in B that is not part of A's interface, does this mean that the object is no longer a Decorator, in the strict sense of the pattern? Furthermore, why is it important that a decorator object's interface conforms to the interface of the component it decorates?

Answer

If the client code attempts to call a method in B that is not part of A’s interface, then it means that the client can tell the difference between a decorated component and an undecorated one, and it depends on the decoration. It violates the intent of the decorator pattern. In strict sense of the pattern, it is no longer a Decorator.

The decorator pattern provides flexibilities by conforming to the interface of the components it decorates. And it allows decorator’s presence transparent to the client and the client can treat decorated and undecorated one uniformly. This transparency of the decorator also lets there to be unlimited number of decorators as needed.

 

 

Adapter

Would you ever create an Adapter that has the same interface as the object that it adapts? Would your Adapter then be a Proxy?

Answer

An Adapter can have the same interface as the object that it adapts because a method in the adapter and adaptee (having the same interface) may do different operations on different kinds of data. In this case, the Adapter probably has more functions which requires the adaptee method. 

It would still be Adapter because a proxy is usually used as a virtual placeholder for the real subject or to restrict access not as an interface to some classes.

 

 

Facade

1) How complex must a sub-system be in order to justify using a facade?

Answer

When there are may dependencies between clients and the implementation classes of an abstraction, using a façade is justified because it decouples the sub-system from clients and other subsystems. It is still possible that the sub-system consists of one class in case that it gets more complex as it evolves or breaking down the subsystem into several classes helps decoupling, portability and independence. 

Facade

2) What are the additional uses of a facade with respect to an organization of designers and developers with varying abilities? What are the political ramifications?

Answer

The façade shields clients from complicated sub-system. So, the developers or designers in the beginning level can still implement some basic modules that do not require the knowledge of all the complex details in the subsystem with the simple interface provided by the façade pattern.  While to advanced and experienced developer façade pattern does not prevent applications from using sub-system classes if they need to.

 

 

Template Method

The Template Method relies on inheritance. Would it be possible to get the same functionality of a Template Method, using object composition? What would some of the tradeoffs be?

Answer

We can get the same functionality of a Template Method using object composition instead of inheritance.

 The concrete class can maintain the pointer to the object that implements a template method so that it can use functions that are needed in the template algorithm and implement the primitive operations to carry out its specific steps. Then the concrete class contains all steps of the template algorithm while in inheritance case the concrete class only needs to have specific steps.  The code using object composition would not be as clear and simple as the code using inheritance. And if there are some changes in those invariant parts, then all those concrete class should be changed accordingly.

 

 

Mediator

Since a Mediator becomes a repository for logic, can the code that implements this logic begin to get overly complex, possible resembling spaghetti code? How could this potential problem be solved?

Answer

It is possible that the code using Mediator gets overly complex when the interactions among objects in the system itself are complicated. One possible approach would be to divide the mediator into a set of mediators such that we may group the communication among objects in a hierarchical structure.  I.e. Break down the system into several subsystems and use mediator pattern for each subsystem. Even though we have more mediators to handle, each mediator of the subsystem has simpler structure than one mediator that controls communication in the whole system. Then communication between those subsystems can be managed by another mediator.

 

 

Chain of Responsibility

1) How does the Chain of Responsibility pattern differ from the Decorator pattern or from a linked list?

Answer

The Chain of Responsibility is used when each object does not need to take responsibilities while the Decorator pattern is used to attach responsibilities to an object dynamically.  In the chain of responsibility, each object may or may not accept the request and handle it. The request keeps passed to the next object and the receipt of the request is not even guaranteed.  And each object is not required to confirm to a shared interface as the decorator pattern is.

Chain of Responsibility

2) Is it helpful to look at patterns from a structural perspective? In other words, if you see how a set of patterns are the same in terms of how they are programmed, does that help you to understand when to apply them to a design?

Answer

It would be helpful to analyze relations between classes in different intents and use patterns flexibly.

 

 

Mememto

The authors write that the "Caretaker" participant never operates on or examines the contents of a memento. Can you consider a case where a Caretaker would in fact need to know the identity of a memento and thus need the ability to examine or query the contents of that memento? Would this break something in the pattern?

Answer

It could be useful if a caretaker checks mementos to see if the state information in mementos is valid. Then the caretaker and the originator are coupled and breaks the data encapsulation boundaries in the memento pattern.

 

 

Command

In the Motivation section of the Command pattern, an application's menu system is described. An application has a Menu, which in turn has MenuItems, which in turn execute commands when they are clicked. What happens if the command needs some information about the application in order to do its job? How would the command have access to such information such that new commands could easily be written that would also have access to the information they need?

Answer

One method is to have the object of a command subclass contain information of the application it needs when instantiating the object by passing the reference to the application or to the information. The command object can access the information using this reference. But the application should provide each menu item with one command object when using this approach.

Another method is to pass the information to the execute method as parameters but each command object does not necessarily need the same information. So, the first approach is better to write new command such that it would have the access to the information they need.

 

 

State

If something has only two to three states, is it overkill to use the State pattern?

Answer

When there are only two or three states, it may be better to use conditional logic instead of using State pattern. However, if it is possible to add more states and change states, then it is desirable to use state pattern because it simplifies the design and adding more states is easy.  State pattern also localize the state-specific behavior and partition behavior for different states.

 

 

Flyweight

1) What is a non-GUI example of a flyweight?

Answer

Our project team did not adopt Flyweight pattern but it can be used for a ballot object in online voting system. Personal information of individual voter can be intrinsic state in the Concrete Flyweight object and static data such as questions, choices, information about elections can be extrinsic state, shared data.

Flyweight

2) What is the minimum configuration for using flyweight? Do you need to be working with thousands of objects, hundreds, tens?

Answer

We have to check if replacing a set of object with relatively few shared objects after extrinsic states are removed saves the storage.  And there must be at least two flyweights. The more flyweights are shared, the more resources are saved.  Then flyweight saves the storage space.

 

 

Visitor

One issue with the Visitor pattern involves cyclicality. When you add a new Visitor, you must make changes to existing code. How would you work around this possible problem?

Answer

In my opinion, adding a new Visitor does not require to change the existing code.  The visitor pattern makes it hard to add new subclasses of Element because each new Concrete element result in a new abstract operation on Visitor and a related implementation in every Concrete Visitor class. We can get around this problem by providing some default implementation in Visitor that can be inherited by most of the Concrete Visitors.