Introduction
Hi friends, please do not think you get an architecture position by reading interview questions. But yes there should be some kind of reference which will help you quickly revise what are the definition. Just by reading these answers you get to a position where you are aware of the fundamentals. But if you have not really worked you will surely fail with scenario based questions. So use this as a quick revision rather than a shot cut.
What are design patterns?
Design patterns are documented tried and tested solutions for recurring problems in a given context. So basically you have a problem context and the proposed solution for the same. Design patterns existed in some or other form right from the inception stage of software development. Let's say if you want to implement a sorting algorithm the first thing comes to mind is bubble sort. So the problem is sorting and solution is bubble sort. Same holds true for design patterns.
Which are the three main categories of design patterns?
There are three basic classifications of patterns Creational, Structural, and Behavioral patterns.
Creational Patterns
Abstract Factory : Creates an instance of several families of classes
Builder : Separates object construction from its representation
Factory Method : Creates an instance of several derived classes
Prototype : A fully initialized instance to be copied or cloned
Singleton : A class in which only a single instance can exist
Note
The best way to remember Creational pattern is by remembering ABFPS (Abraham Became First President of States).
Structural Patterns
Adapter : Match interfaces of different classes .
Bridge : Separates an object's abstraction from its implementation.
Composite : A tree structure of simple and composite objects.
Decorator : Add responsibilities to objects dynamically.
Flyweight : A fine-grained instance used for efficient sharing.
Proxy : An object representing another object.
Note
To remember structural pattern best is (ABCDFFP)
Behavioral Patterns
Mediator : Defines simplified communication between classes.
Memento : Capture and restore an object's internal state.
Interpreter : A way to include language elements in a program.
Iterator : Sequentially access the elements of a collection.
Chain of Resp : A way of passing a request between a chain of objects.
Command : Encapsulate a command request as an object.
State : Alter an object's behavior when its state changes.
Strategy : Encapsulates an algorithm inside a class.
Observer : A way of notifying change to a number of classes.
Template Method : Defer the exact steps of an algorithm to a subclass.
Visitor : Defines a new operation to a class without change.
Note: Just remember Music....... 2 MICS On TV (MMIICCSSOTV).
Note : In the further section we will be covering all the above design patterns in a more detail manner.
Can you explain factory pattern?
Factory pattern is one of the types of creational patterns. You can make out from the name factory itself it's meant to construct and create something. In software architecture world factory pattern is meant to centralize creation of objects. Below is a code snippet of a client which has different types of invoices. These invoices are created depending on the invoice type specified by the client. There are two issues with the code below :
First we have lots of 'new' keyword scattered in the client. In other ways the client is loaded with lot of object creational activities which can make the client logic very complicated.
Second issue is that the client needs to be aware of all types of invoices. So if we are adding one more invoice class type called as 'InvoiceWithFooter' we need to reference the new class in the client and recompile the client also.
Figure 1. Different types of invoice
Taking these issues as our base we will now look in to how factory pattern can help us solve the same. Below figure 'Factory Pattern' shows two concrete classes 'ClsInvoiceWithHeader' and 'ClsInvoiceWithOutHeader'.
The
first issue was that these classes are in direct contact with client which leads to lot of 'new' keyword scattered in the client code. This is removed by introducing a new class 'ClsFactoryInvoice' which does all the creation of objects.
The
second issue was that the client code is aware of both the concrete classes i.e. 'ClsInvoiceWithHeader' and 'ClsInvoiceWithOutHeader'. This leads to recompiling of the client code when we add new invoice types. For instance if we add 'ClsInvoiceWithFooter' client code needs to be changed and recompiled accordingly. To remove this issue we have introduced a common interface 'IInvoice'. Both the concrete classes 'ClsInvoiceWithHeader' and 'ClsInvoiceWithOutHeader' inherit and implement the 'IInvoice' interface.
The client references only the 'IInvoice' interface which results in zero connection between client and the concrete classes ( 'ClsInvoiceWithHeader' and 'ClsInvoiceWithOutHeader'). So now if we add new concrete invoice class we do not need to change any thing at the client side.
In one line the creation of objects is taken care by 'ClsFactoryInvoice' and the client disconnection from the concrete classes is taken care by 'IInvoice' interface.
Figure 2. Factory pattern
Below are the code snippets of how actually factory pattern can be implemented in C#. In order to avoid recompiling the client we have introduced the invoice interface 'IInvoice'. Both the concrete classes 'ClsInvoiceWithOutHeaders' and 'ClsInvoiceWithHeader' inherit and implement the 'IInvoice' interface.
Figure 3. Interface and concrete classes
We have also introduced an extra class 'ClsFactoryInvoice' with a function 'getInvoice()' which will generate objects of both the invoices depending on 'intInvoiceType' value. In short we have centralized the logic of object creation in the 'ClsFactoryInvoice'. The client calls the 'getInvoice' function to generate the invoice classes. One of the most important points to be noted is that client only refers to 'IInvoice' type and the factory class 'ClsFactoryInvoice' also gives the same type of reference. This helps the client to be complete detached from the concrete classes, so now when we add new classes and invoice types we do not need to recompile the client.
Figure 4. Factory class which generates objects
Note : The above example is given in C# . Even if you are from some other technology you can still map the concept accordingly. You can get source code from the CD in 'FactoryPattern' folder.
Can you explain abstract factory pattern?
Abstract factory expands on the basic factory pattern. Abstract factory helps us to unite similar factory pattern classes in to one unified interface. So basically all the common factory patterns now inherit from a common abstract factory class which unifies them in a common class. All other things related to factory pattern remain same as discussed in the previous question.
A factory class helps us to centralize the creation of classes and types. Abstract factory helps us to bring uniformity between related factory patterns which leads more simplified interface for the client.
Figure 5. Abstract factory unifies related factory patterns
Now that we know the basic lets try to understand the details of how abstract factory patterns are actually implemented. As said previously we have the factory pattern classes (factory1 and factory2) tied up to a common abstract factory (AbstractFactory Interface) via inheritance. Factory classes stand on the top of concrete classes which are again derived from common interface. For instance in figure 'Implementation of abstract factory' both the concrete classes 'product1' and 'product2' inherits from one interface i.e. 'common'. The client who wants to use the concrete class will only interact with the abstract factory and the common interface from which the concrete classes inherit.
Figure 6. Implementation of abstract factory
Now let's have a look at how we can practically implement abstract factory in actual code. We have scenario where we have UI creational activities for textboxes and buttons through their own centralized factory classes 'ClsFactoryButton' and 'ClsFactoryText'. Both these classes inherit from common interface 'InterfaceRender'. Both the factories 'ClsFactoryButton' and 'ClsFactoryText' inherits from the common factory 'ClsAbstractFactory'. Figure 'Example for AbstractFactory' shows how these classes are arranged and the client code for the same. One of the important points to be noted about the client code is that it does not interact with the concrete classes. For object creation it uses the abstract factory ( ClsAbstractFactory ) and for calling the concrete class implementation it calls the methods via the interface 'InterfaceRender'. So the 'ClsAbstractFactory' class provides a common interface for both factories 'ClsFactoryButton' and 'ClsFactoryText'.
Figure 7. Example for abstract factory
Note: We have provided a code sample in C# in the 'AbstractFactory' folder. People who are from different technology can compare easily the implementation in their own language.
We will just run through the sample code for abstract factory. Below code snippet 'Abstract factory and factory code snippet' shows how the factory pattern classes inherit from abstract factory.
Figure 8. Abstract factory and factory code snippet
Figure 'Common Interface for concrete classes' how the concrete classes inherits from a common interface 'InterFaceRender' which enforces the method 'render' in all the concrete classes.
Figure 9. Common interface for concrete classes
The final thing is the client code which uses the interface 'InterfaceRender' and abstract factory 'ClsAbstractFactory' to call and create the objects. One of the important points about the code is that it is completely isolated from the concrete classes. Due to this any changes in concrete classes like adding and removing concrete classes does not need client level changes.
Figure 10. Client, interface and abstract factory
Can you explain builder pattern?
Builder falls under the type of creational pattern category. Builder pattern helps us to separate the construction of a complex object from its representation so that the same construction process can create different representations. Builder pattern is useful when the construction of the object is very complex. The main objective is to separate the construction of objects and their representations. If we are able to separate the construction and representation, we can then get many representations from the same construction.
Figure 11. Builder concept
To understand what we mean by construction and representation lets take the example of the below 'Tea preparation' sequence.
You can see from the figure 'Tea preparation' from the same preparation steps we can get three representation of tea's (i.e. Tea with out sugar, tea with sugar / milk and tea with out milk).
Figure 12. Tea preparation
Now let's take a real time example in software world to see how builder can separate the complex creation and its representation. Consider we have application where we need the same report to be displayed in either 'PDF' or 'EXCEL' format. Figure 'Request a report' shows the series of steps to achieve the same. Depending on report type a new report is created, report type is set, headers and footers of the report are set and finally we get the report for display.
Figure 13. Request a report
Now let's take a different view of the problem as shown in figure 'Different View'. The same flow defined in 'Request a report' is now analyzed in representations and common construction. The construction process is same for both the types of reports but they result in different representations.
Figure 14. Different View
We will take the same report problem and try to solve the same using builder patterns. There are three main parts when you want to implement builder patterns.
Builder : Builder is responsible for defining the construction process for individual parts. Builder has those individual processes to initialize and configure the product.
Director : Director takes those individual processes from the builder and defines the sequence to build the product.
Product : Product is the final object which is produced from the builder and director coordination.
First let's have a look at the builder class hierarchy. We have a abstract class called as 'ReportBuilder' from which custom builders like 'ReportPDF' builder and 'ReportEXCEL' builder will be built.
Figure 15. Builder class hierarchy
Figure 'Builder classes in actual code' shows the methods of the classes. To generate report we need to first Create a new report, set the report type (to EXCEL or PDF) , set report headers , set the report footers and finally get the report. We have defined two custom builders one for 'PDF' (ReportPDF) and other for 'EXCEL' (ReportExcel). These two custom builders define there own process according to the report type.
Figure 16. Builder classes in actual code
Now let's understand how director will work. Class 'clsDirector' takes the builder and calls the individual method process in a sequential manner. So director is like a driver who takes all the individual processes and calls them in sequential manner to generate the final product, which is the report in this case. Figure 'Director in action' shows how the method 'MakeReport' calls the individual process to generate the report product by PDF or EXCEL.
Figure 17. Director in action
The third component in the builder is the product which is nothing but the report class in this case.
Figure 18. The report class
Now let's take a top view of the builder project. Figure 'Client,builder,director and product' shows how they work to achieve the builder pattern. Client creates the object of the director class and passes the appropriate builder to initialize the product. Depending on the builder the product is initialized/created and finally sent to the client.
Figure 19. Client, builder, director and product
The output is something like this. We can see two report types displayed with their headers according to the builder.
Figure 20. Final output of builder
Can you explain prototype pattern?
Prototype pattern falls in the section of creational pattern. It gives us a way to create new objects from the existing instance of the object. In one sentence we clone the existing object with its data. By cloning any changes to the cloned object does not affect the original object value. If you are thinking by just setting objects we can get a clone then you have mistaken it. By setting one object to other object we set the reference of object BYREF. So changing the new object also changed the original object. To understand the BYREF fundamental more clearly consider the figure 'BYREF' below. Following is the sequence of the below code:
- In the first step we have created the first object i.e. obj1 from class1.
- In the second step we have created the second object i.e. obj2 from class1.
- In the third step we set the values of the old object i.e. obj1 to 'old value'.
- In the fourth step we set the obj1 to obj2.
- In the fifth step we change the obj2 value.
- Now we display both the values and we have found that both the objects have the new value.
Figure 21. BYREF
The conclusion of the above example is that objects when set to other objects are set BYREF. So changing new object values also changes the old object value.
There are many instances when we want the new copy object changes should not affect the old object. The answer to this is prototype patterns.
Lets look how we can achieve the same using C#. In the below figure 'Prototype in action' we have the customer class 'ClsCustomer' which needs to be cloned. This can be achieved in C# my using the 'MemberWiseClone' method. In JAVA we have the 'Clone' method to achieve the same. In the same code we have also shown the client code. We have created two objects of the customer class 'obj1' and 'obj2'. Any changes to 'obj2' will not affect 'obj1' as it's a complete cloned copy.
Figure 22. Prototype in action
Note : You can get the above sample in the CD in 'Prototype' folder. In C# we use the 'MemberWiseClone' function while in JAVA we have the 'Clone' function to achieve the same.
Can you explain shallow copy and deep copy in prototype patterns?
There are two types of cloning for prototype patterns. One is the shallow cloning which you have just read in the first question. In shallow copy only that object is cloned, any objects containing in that object is not cloned. For instance consider the figure 'Deep cloning in action' we have a customer class and we have an address class aggregated inside the customer class. 'MemberWiseClone' will only clone the customer class 'ClsCustomer' but not the 'ClsAddress' class. So we added the 'MemberWiseClone' function in the address class also. Now when we call the 'getClone' function we call the parent cloning function and also the child cloning function, which leads to cloning of the complete object. When the parent objects are cloned with their containing objects it's called as deep cloning and when only the parent is clones its termed as shallow cloning.
Figure 23. Deep cloning in action
Can you explain singleton pattern?
There are situations in a project where we want only one instance of the object to be created and shared between the clients. No client can create an instance of the object from outside. There is only one instance of the class which is shared across the clients. Below are the steps to make a singleton pattern :-
- Define the constructor as private.
- Define the instances and methods as static.
Below is a code snippet of a singleton in C#. We have defined the constructor as private, defined all the instance and methods using the static keyword as shown in the below code snippet figure 'Singleton in action'. The static keyword ensures that you only one instance of the object is created and you can all the methods of the class with out creating the object. As we have made the constructor private, we need to call the class directly.
Figure 24. Singleton in action
Note : In JAVA to create singleton classes we use the STATIC keyword , so its same as in C#. You can get a sample C# code for singleton in the 'singleton' folder.
Can you explain command patterns?
Command pattern allows a request to exist as an object. Ok let's understand what it means. Consider the figure 'Menu and Commands' we have different actions depending on which menu is clicked. So depending on which menu is clicked we have passed a string which will have the action text in the action string. Depending on the action string we will execute the action. The bad thing about the code is it has lot of 'IF' condition which makes the coding more cryptic.
Figure 25. Menu and Commands
Command pattern moves the above action in to objects. These objects when executed actually execute the command.
As said previously every command is an object. We first prepare individual classes for every action i.e. exit, open, file and print. Al l the above actions are wrapped in to classes like Exit action is wrapped in 'clsExecuteExit' , open action is wrapped in 'clsExecuteOpen', print action is wrapped in 'clsExecutePrint' and so on. All these classes are inherited from a common interface 'IExecute'.
Figure 26. Objects and Command
Using all the action classes we can now make the invoker. The main work of invoker is to map the action with the classes which have the action.
So we have added all the actions in one collection i.e. the arraylist. We have exposed a method 'getCommand' which takes a string and gives back the abstract object 'IExecute'. The client code is now neat and clean. All the 'IF' conditions are now moved to the 'clsInvoker' class.
Figure 27. Invoker and the clean client
What is Interpreter pattern?
Interpreter pattern allows us to interpret grammar in to code solutions. Ok, what does that mean?. Grammars are mapped to classes to arrive to a solution. For instance 72 can be mapped to 'clsMinus' class. In one line interpreter pattern gives us the solution of how to write an interpreter which can read a grammar and execute the same in the code. For instance below is a simple example where we can give the date format grammar and the interpreter will convert the same in to code solutions and give the desired output.
Figure 28. Date Grammar
Let's make an interpreter for date formats as shown in figure 'Date Grammar'. Before we start lets understand the different components of interpreter pattern and then we will map the same to make the date grammar. Context contains the data and the logic part contains the logic which will convert the context to readable format.
Figure 29. Context and Logic
Let's understand what is the grammar in the date format is. To define any grammar we should first break grammar in small logical components. Figure 'Grammar mapped to classes' show how different components are identified and then mapped to classes which will have the logic to implement only that portion of the grammar. So we have broken the date format in to four components Month, Day, Year and the separator. For all these four components we will define separate classes which will contain the logic as shown in figure 'Grammar mapped to classes'. So we will be creating different classes for the various components of the date format.
Figure 30. Grammar mapped to classes
As said there are two classes one is the expression classes which contain logic and the other is the context class which contain data as shown in figure 'Expression and Context classes'. We have defined all the expression parsing in different classes, all these classes inherit from common interface 'ClsAbstractExpression' with a method 'Evaluate'. The 'Evaluate' method takes a context class which has the data; this method parses data according to the expression logic. For instance 'ClsYearExpression' replaces the 'YYYY' with the year value,''ClsMonthExpression' replaces the 'MM' with month and so on.
Figure 31. Class diagram for interpreter
Figure 32. Expression and Context classes
Now that we have separate expression parsing logic in different classes, let's look at how the client will use the iterator logic. The client first passes the date grammar format to the context class. Depending on the date format we now start adding the expressions in a collection. Finally we just loop and call the 'Evaluate' method. Once all the evaluate methods are called we display the output.
Figure 33. Client Interpreter logic
Note :- You can find the code for interpreter in 'Interpeter' folder.
Can you explain iterator pattern?
Iterator pattern allows sequential access of elements with out exposing the inside code. Let's understand what it means. Let's say you have a collection of records which you want to browse sequentially and also maintain the current place which recordset is browsed, then the answer is iterator pattern. It's the most common and unknowingly used pattern. Whenever you use a 'foreach' (It allows us to loop through a collection sequentially) loop you are already using iterator pattern to some extent.
Figure 34. Iterator business logic
In figure 'Iterator business logic' we have the 'clsIterator' class which has collection of customer classes. So we have defined an array list inside the 'clsIterator' class and a 'FillObjects' method which loads the array list with data. The customer collection array list is private and customer data can be looked up by using the index of the array list. So we have public function like 'getByIndex' ( which can look up using a particular index) , 'Prev' ( Gets the previous customer in the collection , 'Next' (Gets the next customer in the collection), 'getFirst' ( Gets the first customer in the collection ) and 'getLast' ( Gets the last customer in the collection).
So the client is exposed only these functions. These functions take care of accessing the collection sequentially and also it remembers which index is accessed.
Below figures 'Client Iterator Logic' shows how the 'ObjIterator' object which is created from class 'clsIterator' is used to display next, previous, last, first and customer by index.
Figure 35. Client Iterator logic
Note :- You can get a sample C# code in the 'Iterator' folder of the CD provided with this book.
Can you explain mediator pattern?
Many a times in projects communication between components are complex. Due to this the logic between the components becomes very complex. Mediator pattern helps the objects to communicate in a disassociated manner, which leads to minimizing complexity.
Figure 36. Mediator sample example
Let's consider the figure 'Mediator sample example' which depicts a true scenario of the need of mediator pattern. It's a very user-friendly user interface. It has three typical scenarios.
Scenario 1 :- When a user writes in the text box it should enable the add and the clear button. In case there is nothing in the text box it should disable the add and the clear button.
Figure 37. Scenario 1
Scenario 2 :- When the user clicks on the add button the data should get entered in the list box. Once the data is entered in the list box it should clear the text box and disable the add and clear button.
Figure 38. Scenario 2
Scenario 3 :- If the user click the clear button it should clear the name text box and disable the add and clear button.
Figure 39. Scenario 3
Now looking at the above scenarios for the UI we can conclude how complex the interaction will be in between these UI's. Below figure 'Complex interactions between components' depicts the logical complexity.
Figure 40. Complex interactions between components
Ok now let me give you a nice picture as shown below 'Simplifying using mediator'. Rather than components communicating directly with each other if they communicate to centralized component like mediator and then mediator takes care of sending those messages to other components, logic will be neat and clean.
Figure 41. Simplifying using mediator
Now let's look at how the code will look. We will be using C# but you can easily replicate the thought to JAVA or any other language of your choice. Below figure 'Mediator class' shows the complete code overview of what the mediator class will look like.
The first thing the mediator class does is takes the references of the classes which have the complex communication. So here we have exposed three overloaded methods by name 'Register'. 'Register' method takes the text box object and the button objects. The interaction scenarios are centralized in 'ClickAddButton','TextChange' and 'ClickClearButton' methods. These methods will take care of the enable and disable of UI components according to scenarios.
Figure 42. Mediator class
The client logic is pretty neat and cool now. In the constructor we first register all the components with complex interactions with the mediator. Now for every scenario we just call the mediator methods. In short when there is a text change we can the 'TextChange' method of the mediator, when the user clicks add we call the 'ClickAddButton' and for clear click we call the 'ClickClearButton'.
Figure 43. Mediator client logic
Note :- You can get the C# code for the above mediator example in the 'mediator' folder.
Can you explain memento pattern?
Memento pattern is the way to capture objects internal state with out violating encapsulation. Memento pattern helps us to store a snapshot which can be reverted at any moment of time by the object. Let's understand what it means in practical sense. Consider figure 'Memento practical example', it shows a customer screen. Let's say if the user starts editing a customer record and he makes some changes. Later he feels that he has done something wrong and he wants to revert back to the original data. This is where memento comes in to play. It will help us store a copy of data and in case the user presses cancel the object restores to its original state.
Figure 44. Memento practical example
Let's try to complete the same example in C# for the customer UI which we had just gone through. Below is the customer class 'clsCustomer' which has the aggregated memento class 'clsCustomerMemento' which will hold the snapshot of the data. The memento class 'clsCustomerMemento' is the exact replica ( excluding methods ) of the customer class 'clsCustomer'. When the customer class 'clsCustomer' gets initialized the memento class also gets initialized. When the customer class data is changed the memento class snapshot is not changed. The 'Revert' method sets back the memento data to the main class.
Figure 45. Customer class for memento
The client code is pretty simple. We create the customer class. In case we have issues we click the cancel button which in turn calls the 'revert' method and reverts the changed data back to the memento snapshot data. Figure 'Memento client code' shows the same in a pictorial format.
Figure 46. Memento client code
Note :- A sample code in C# for memento is available in the memento folder of the CD.
Can you explain observer pattern?
Observer pattern helps us to communicate between parent class and its associated or dependent classes. There are two important concepts in observer pattern 'Subject' and 'Observers'. The subject sends notifications while observers receive notifications if they are registered with the subject. Below figure 'Subject and observers' shows how the application (subject) sends notification to all observers (email, event log and SMS). You can map this example to publisher and subscriber model. The publisher is the application and subscribers are email, event log and sms.
Figure 47. Subject and Observers
Let's try to code the same example which we have defined in the previous section. First let's have a look at the subscribers / notification classes. Figure 'Subscriber classes' shows the same in a pictorial format. So we have a common interface for all subscribers i.e. 'INotification' which has a 'notify' method. This interface 'INotification' is implemented by all concrete notification classes. All concrete notification classes define their own notification methodology. For the current scenario we have just displayed a print saying the particular notification is executed.
Figure 48. Subscriber classes
As said previously there are two sections in an observer pattern one is the observer/subscriber which we have covered in the previous section and second is the publisher or the subject.
The publisher has a collection of arraylist which will have all subscribers added who are interested in receiving the notifications. Using 'addNotification' and 'removeNotification' we can add and remove the subscribers from the arraylist. 'NotifyAll' method loops through all the subscribers and send the notification.
Figure 49. Publisher/Subject classes
Now that we have an idea about the publisher and subscriber classes lets code the client and see observer in action. Below is a code for observer client snippet. So first we create the object of the notifier which has collection of subscriber objects. We add all the subscribers who are needed to be notified in the collection.
Now if the customer code length is above 10 characters then tell notify all the subscribers about the same.
Figure 50. Observer client code
More on design patterns: Here is detailed article on Design Patterns in .NET and C#: