Polis Town - Index - Directory
Creational Patterns Abstract Factory Provide an interface for creating families of related or dependent objects without specifying their concrete classes. Builder Separate the construction of a complex object from its representation so that the same construction process can create different representations. Factory Method Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. Prototype Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype. Singleton Ensure a class only has one instance, and provide a global point of access to it. Structural Patterns Adapter Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. Bridge Decouple an abstraction from its implementation so that the two can vary independently. Composite Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. Decorator Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. Facade Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use. Flyweight Use sharing to support large numbers of fine-grained objects efficiently. Proxy Provide a surrogate or placeholder for another object to control access to it. Behavioral Patterns Chain of Responsibility Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it. Command Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations. Interpreter Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language. Iterator Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation. Mediator Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently. Memento Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later. Observer Define a one-to-many dependency between objects so that when one object changes state, all its dependants are notified and updated automatically. State Allow an object to alter its behavior when its internal state changes. The object will appear to change its class. Strategy Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. Template Method Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure. Visitor Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
1. Creational Patterns Sometimes creational patterns are competitors: there are cases when either Prototype or Abstract Factory could be used profitably. At other times they are complementory: Abstract Factory might store a set of Prototypes from which to clone and return product objects , Builder can use one of the other patterns to implement which components get built. Abstract Factory, Builder, and Prototypecan use Singleton in their implementation. Abstract Factory, Builder, and Prototype define a factory object that's responsible for knowing and creating the class of product objects, and make it a parameter of the system. Abstract Factory has the factory object producing objects of several classes. Builder has the factory object building a complex product incrementally using a correspondingly complex protocol. Prototype has the factory object (aka prototype) building a product by copying a prototype object. Abstract Factory classes are often implemented with Factory Methods, but they can also be implemented using Prototype. Abstract Factory can be used as an alternative to Facade to hide platform-specific classes. Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately. Builder is to creation as Strategy is to algorithm. Builder often builds a Composite. Factory Methods are usually called within Template Methods. Factory Method: creation through inheritance. Prototype: creation through delegation. Often, designs start out using Factory Method(less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed. Prototype doesn't require subclassing, but it does require an Initialize operation. Factory Methodrequires subclassing, but doesn't require Initialize. Designs that make heavy use of the Compositeand Decorator patterns often can benefit from Prototype as well. 2. Structural Patterns Adapter makes things work after they're designed; Bridge makes them work before they are. Bridge is designed up-front to let the abstraction and the implementation vary independently. Adapter is retrofitted to make unrelated classes work together. Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface. Adapter changes an object's interface, Decoratorenhances an object's responsibilities. Decorator is thus more transparent to the client. As a consequence, Decorator supports recursive composition, which isn't possible with pure Adapters. Composite and Decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open-ended number of objects. Composite can be traversed with Iterator. Visitorcan apply an operation over a Composite. Composite could use Chain of Responsibility to let components access global properties through their parent. It could also use Decorator to override these properties on parts of the composition. It could use Observer to tie one object structure to another and State to let a component change its behavior as its state changes. Composite can let you compose a Mediator out of smaller pieces through recursive composition. Decorator lets you change the skin of an object. Strategy lets you change the guts. Decorator is designed to let you add responsibilities to objects without subclassing. Composite's focus is not on embellishment but on representation. These intents are distinct but complementary. Consequently, Composite and Decorator are often used in concert. Decorator and Proxy have different purposes but similar structures. Both describe how to provide a level of indirection to another object, and the implementations keep a reference to the object to which they forward requests. Facade defines a new interface, whereas Adapterreuses an old interface. Remember that Adaptermakes two existing interfaces work together as opposed to defining an entirely new one. Facade objects are often Singletons because only one Facade object is required. Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediatorabstracts/centralizes arbitrary communication between colleague objects, it routinely "adds value", and it is known/referenced by the colleague objects. In contrast, Facade defines a simpler interface to a subsystem, it doesn't add new functionality, and it is not known by the subsystem classes. Abstract Factory can be used as an alternative to Facade to hide platform-specific classes. Whereas Flyweight shows how to make lots of little objects, Facade shows how to make a single object represent an entire subsystem. Flyweight is often combined with Composite to implement shared leaf nodes. Flyweight explains when and how State objects can be shared. 3. Behavioral Patterns Behavioral patterns are concerned with the assignment of responsibilities between objects, or, encapsulating behavior in an object and delegating requests to it. Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Chain of Responsibility passes a sender request along a chain of potential receivers. Command normally specifies a sender-receiver connection with a subclass. Mediator has senders and receivers reference each other indirectly. Observer defines a very decoupled interface that allows for multiple receivers to be configured at run-time. Chain of Responsibility can use Command to represent requests as objects. Chain of Responsibility is often applied in conjunction with Composite. There, a component's parent can act as its successor. Command and Memento act as magic tokens to be passed around and invoked at a later time. In Command, the token represents a request; in Memento, it represents the internal state of an object at a particular time. Polymorphism is important to Command, but not to Mementobecause its interface is so narrow that a memento can only be passed as a value. Command can use Memento to maintain the state required for an undo operation. MacroCommands can be implemented with Composite. A Command that must be copied before being placed on a history list acts as a Prototype. Interpreter can use State to define parsing contexts. The abstract syntax tree of Interpreter is a Composite (therefore Iterator and Visitor are also applicable). Terminal symbols within Interpreter's abstract syntax tree can be shared with Flyweight. Iterator can traverse a Composite. Visitor can apply an operation over a Composite. Polymorphic Iterators rely on Factory Methods to instantiate the appropriate Iterator subclass. Mediator and Observer are competing patterns. The difference between them is that Observerdistributes communication by introducing "observer" and "subject" objects, whereas a Mediator object encapsulates the communication between other objects. We've found it easier to make reusable Observers and Subjects than to make reusable Mediators. On the other hand, Mediator can leverage Observer for dynamically registering colleagues and communicating with them. Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediatorabstracts/centralizes arbitrary communication between colleague objects, it routinely "adds value", and it is known/referenced by the colleague objects (i.e. it defines a multidirectional protocol). In contrast, Facade defines a simpler interface to a subsystem, it doesn't add new functionality, and it is not known by the subsystem classes (i.e. it defines a unidirectional protocol where it makes requests of the subsystem classes but not vice versa). Memento is often used in conjunction with Iterator. An Iterator can use a Memento to capture the state of an iteration. The Iterator stores the Memento internally. State is like Strategy except in its intent. Flyweight explains when and how State objects can be shared. State objects are often Singletons. Strategy lets you change the guts of an object. Decorator lets you change the skin. Strategy is to algorithm. as Builder is to creation. Strategy has 2 different implementations, the first is similar to State. The difference is in binding times (Strategy is a bind-once pattern, whereas State is more dynamic). Strategy objects often make good Flyweights. Strategy is like Template Method except in its granularity. Template Method uses inheritance to vary part of an algorithm. Strategy uses delegation to vary the entire algorithm. The Visitor pattern is like a more powerful Command pattern because the visitor may initiate whatever is appropriate for the kind of object it encounters.
1. Builder v/s Decorator 2. Template Method v/s Strategy 3. Chain of Responsibility v/s Decorator 4. State v/s Strategy 5. Proxy v/s Decorator 6. Class Adapter v/s Object Adapter 7. Proxy v/s Decorator v/s Adapter v/s Bridge 8. Decorator v/s Bridge 9. Bridge v/s Strategy 10. Mediator v/s Facade 11. Prototype v/s Flyweight 12. In Java, how will you prevent cloning of a Singleton object? 13. What are Software Design Principles? 14. Open Close Principle 15. Dependency Inversion Principle 16. Interface Segregation Principle 17. Single Responsibility Principle 18. Liskov's Substitution Principle 1. Builder v/s Decorator Builder Pattern makes it easy to construct an object which is extensible in independent directions at construction time, while the Decorator Pattern lets you add extensions to functionality to an object after construction time. Using the decorator pattern to construct objects is bad because it leaves the object in an inconsistent (or at least incorrect) state until all the required decorators are in place. 2. Template Method v/s Strategy "Template method pattern: compile-time algorithm selection by subclassing" With the Template method pattern this happens at compile-time by subclassing the template. Each subclass provides a different concrete algorithm by implementing the template's abstract methods. When a client invokes methods of the template's external interface the template calls its abstract methods (its internal interface) as required to invoke the algorithm. "Strategy pattern: run-time algorithm selection by containment" The Strategy pattern allows an algorithm to be chosen at runtime by containment. The concrete algorithms are implemented by separate classes or functions which are passed to the strategy as a parameter to its constructor or to a setter method. Which algorithm is chosen for this parameter can vary dynamically based on the program's state or inputs. 3. Chain of Responsibility v/s Decorator Chain of Responsibility allows us to process the request and pass it on to the next object in the chain. This give us the ability to break the chain anytime there by allowing only certain hooks to process the request. However, in case of Decorator, it is difficult to prevent other processors/hooks from processing the request. 4. State v/s Strategy The implementation of the State pattern builds on the Strategy pattern. The difference between State and Strategy is in the intent. With Strategy, the choice of algorithm is fairly stable. With State, a change in the state of the "context" object causes it to select from its "palette" of Strategy objects. 5. Proxy v/s Decorator Decorator and Proxy have different purposes but similar structures. Both describe how to provide a level of indirection to another object, and the implementations keep a reference to the object to which they forward requests. 6. Class Adapter v/s Object Adapter Class Adapter uses inheritance and can only wrap a class. It cannot wrap an interface since by definition it must derive from some base class. Object Adapter uses composition and can wrap classes or interfaces, or both. It can do this since it contains, as a private, encapsulated member, the class or interface object instance it wraps. 7. Proxy v/s Decorator v/s Adapter v/s Bridge Proxy, Decorator, Adapter, and Bridge are all variations on "wrapping" a class. But their uses are different. - Proxy could be used when you want to lazy-instantiate an object, or hide the fact that you're calling a remote service, or control access to the object. - Decorator is also called ""Smart Proxy."" This is used when you want to add functionality to an object, but not by extending that object's type. This allows you to do so at runtime. - Adapter is used when you have an abstract interface, and you want to map that interface to another object which has similar functional role, but a different interface. - Bridge is very similar to Adapter, but we call it Bridge when you define both the abstract interface and the underlying implementation. I.e. you're not adapting to some legacy or third-party code, you're the designer of all the code but you need to be able to swap out different implementations. - Facade is a higher-level (read: simpler) interface to a subsystem of one or more classes. Suppose you have a complex concept that requires multiple objects to represent. Making changes to that set of objects is confusing, because you don't always know which object has the method you need to call. That's the time to write a Facade that provides high-level methods for all the complex operations you can do to the collection of objects. Example: a Domain Model for a school section, with methods like countStudents(), reportAttendance(), assignSubstituteTeacher(), and so on. 8. Decorator v/s Bridge The Decorator should match the interface of the object you're decorating. i.e. it has the same methods, and permits interception of the arguments on the way in, and of the result on the way out. You can use this to provide additional behaviour to the decorated object whilst maintaining the same interface/contract. Note that the interface of the Decorator can provide additional functionality to create a more useful object. The Bridge has no such constraint. The client-facing interface can be different from the underlying component providing the implementation, and thus it bridges between the client's interface, and the actual implementation (which may not be client-friendly, subject to change etc.) 9. Bridge v/s Strategy The UML class diagram for the Strategy pattern is the same as the diagram for the Bridge pattern. However, these two design patterns aren't the same in their intent. While the Strategy pattern is meant for behavior, the Bridge pattern is meant for structure. The coupling between the context and the strategies is tighter than the coupling between the abstraction and the implementation in the Bridge pattern. 10. Mediator v/s Facade In the implementation of mediator pattern, subsystem or peers components are aware of the mediator and that interact with it. In the case of facade pattern, subsystems are not aware of the existence of facade. Only facade talks to the subsystems. 11. Prototype v/s Flyweight In Prototype objects' creation go through cloning, it ease object's creation. By making a request for cloning we create new cloned object each time. In Flyweight by making a request we try to reuse as much objects as possible by sharing them. New required object will be created if we don't find such one. It's being done for resource optimization. 12. In Java, how will you prevent cloning of a Singleton object? The clone() method by default is protected, so no class (except those in the same package) would be able to call it on that Singleton instance. Plus, if this Singleton does not implement Cloneable, then even if this method is called, it will give a runtime exception. Plus, the constructor being private, we won't be able to subclass it and thus allow for its cloning. However, if the Singleton class extends another class that does support cloning, it is possible to violate the design principles of the singleton. So, to be absolutely positively 100% certain that a singleton really is a singleton, we must extend the Cloneable interface add a clone() method of our to throw a CloneNotSupportedException. 13. What are Software Design Principles? Software design principles represent a set of guidelines that helps us to avoid having a bad design. The design principles are associated to Robert Martin who gathered them in "Agile Software Development: Principles, Patterns, and Practices". According to Robert Martin there are 3 important characteristics of a bad design that should be avoided: Rigidity - It is hard to change because every change affects too many other parts of the system. Fragility - When you make a change, unexpected parts of the system break. Immobility - It is hard to reuse in another application because it cannot be disentangled from the current application. 14. Open Close Principle "Software entities like classes, modules and functions should be open for extension but closed for modifications." OPC is a generic principle. You can consider it when writing your classes to make sure that when you need to extend their behavior you don't have to change the class but to extend it. The same principle can be applied for modules, packages, libraries. If you have a library containing a set of classes there are many reasons for which you'll prefer to extend it without changing the code that was already written (backward compatibility, regression testing). This is why we have to make sure our modules follow Open Closed Principle. When referring to the classes Open Close Principle can be ensured by use of Abstract Classes and concrete classes for implementing their behavior. This will enforce having Concrete Classes extending Abstract Classes instead of changing them. Some particular cases of this are Template Pattern and Strategy Pattern." 15. Dependency Inversion Principle " High-level modules should not depend on low-level modules. Both should depend on abstractions." " Abstractions should not depend on details. Details should depend on abstractions." Dependency Inversion Principle states that we should decouple high level modules from low level modules, introducing an abstraction layer between the high level classes and low level classes. Further more it inverts the dependency: instead of writing our abstractions based on details, the we should write the details based on abstractions. Dependency Inversion or Inversion of Control are better know terms referring to the way in which the dependencies are realized. In the classical way when a software module(class, framework, etc) need some other module, it initializes and holds a direct reference to it. This will make the 2 modules tight coupled. In order to decouple them the first module will provide a hook(a property, parameter, etc) and an external module controlling the dependencies will inject the reference to the second one. By applying the Dependency Inversion the modules can be easily changed by other modules just changing the dependency module. Factories and Abstract Factories can be used as dependency frameworks, but there are specialized frameworks for that, known as Inversion of Control Container." 16. Interface Segregation Principle " Clients should not be forced to depend upon interfaces that they don't use." This principle teaches us to take care how we write our interfaces. When we write our interfaces we should take care to add only methods that should be there. If we add methods that should not be there the classes implementing the interface will have to implement those methods as well. For example if we create an interface called Worker and add a method lunch break, all the workers will have to implement it. What if the worker is a robot? As a conclusion Interfaces containing methods that are not specific to it are called polluted or fat interfaces. We should avoid them. 17. Single Responsibility Principle " A class should have only one reason to change." In this context a responsibility is considered to be one reason to change. This principle states that if we have 2 reasons to change for a class, we have to split the functionality in two classes. Each class will handle only one responsibility and on future if we need to make one change we are going to make it in the class which handle it. When we need to make a change in a class having more responsibilities the change might affect the other functionality of the classes. Single Responsibility Principle was introduced Tom DeMarco in his book Structured Analysis and Systems Specification, 1979. Robert Martin reinterpreted the concept and defined the responsibility as a reason to change. 18. Liskov's Substitution Principle "Derived types must be completely substitutable for their base types." This principle is just an extension of the Open Close Principle in terms of behavior meaning that we must make sure that new derived classes are extending the base classes without changing their behavior. The new derived classes should be able to replace the base classes without any change in the code. Liskov's Substitution Principle was introduced by Barbara Liskov in a 1987 Conference on Object Oriented Programming Systems Languages and Applications, in Data abstraction and hierarchy
Developers must first seek to understand how to code before they themselves may refactor code effectively.
What is refactoring? A key theme in refactoring code is addressing issues within the internal structure of code while not altering the external behavior of the program being refactored. In some cases, this can mean introducing internal structure where it previously wasn't intentional or thought about before. Refactoring as a process improves the design of code after it is written. While design is a critical phase of the software engineering process, it is often disregarded (not least in PHP); in addition to this, maintaining the structure of code over the long-term requires a continued understanding of the design of software. If a developer takes up a project without understanding how it was originally designed, they may develop upon it in a very crude fashion. In Extreme Programming (XP), a phrase known as Refactor Mercilessly is used, it is selfexplanatory. In XP, refactoring is proposed as a mechanism to keep software design as simple as possible and to avoid needless complexity. As is stated in the rules of XP: Make sure everything is expressed once and only once. In the end it takes less time to produce a system that is well groomed.??????????????
Design Patterns: How to Select a Design Pattern
With more than 20 design patterns in the catalog to choose from, it might be hard to find
the one that addresses a particular design problem, especially if the catalog is new and
unfamiliar to you. Here are several different approaches to finding the design pattern
that's right for your problem:
• Consider how design patterns solve design problems. Section 1.6 discusses how design
patterns help you find appropriate objects, determine object granularity, specify
object interfaces, and several other ways in which design patterns solve design
problems. Referring to these discussions can help guide your search for the right
pattern.
• Scan Intent sections. Section 1.4 (page 8) lists the Intent sections from all the patterns
in the catalog. Read through each pattern's intent to find one or more that sound
relevant to your problem. You can use the classification scheme presented in
Table 1.1 (page 10) to narrow your search.
• Study how patterns interrelate. Figure 1.1 (page 12) shows relationships between
design patterns graphically. Studying these relationships can help direct you to
the right pattern or group of patterns.
• Study patterns of like purpose. The catalog (page 79) has three chapters, one for
creational patterns, another for structural patterns, and a third for behavioral
patterns. Each chapter starts off with introductory comments on the patterns and
concludes with a section that compares and contrasts them. These sections give
you insight into the similarities and differences between patterns of like purpose.
• Examine a cause of redesign. Look at the causes of redesign starting on page 24 to
see if your problem involves one or more of them. Then look at the patterns that
help you avoid the causes of redesign.
• Consider what should be variable in your design. This approach is the opposite of
focusing on the causes of redesign. Instead of considering what might force a
change to a design, consider what you want to be able to change without redesign.
The focus here is on encapsulating the concept that varies, a theme of many design
patterns. Table 1.2 lists the design aspect(s) that design patterns let you vary
independently, thereby letting you change them without redesign.
Design Patterns: How to Use a Design Pattern
Once you've picked a design pattern, how do you use it? Here's a step-by-step approach to applying a design pattern effectively: 1 . Read the pattern once through for an overview. Pay particular attention to the Applicability and Consequences sections to ensure the pattern is right for your problem. 2. Go back and study the Structure, Participants, and Collaborations sections. Make sure you understand the classes and objects in the pattern and how they relate to one another. 3. Look at the Sample Code section to see a concrete example of the pattern in code. Studying the code helps you learn how to implement the pattern. 4. Choose names for pattern participants that are meaningful in the application context. The names for participants in design patterns are usually too abstract to appear directly in an application. Nevertheless, it's useful to incorporate the participant name into the name that appears in the application. That helps make the pattern more explicit in the implementation. For example, if you use the Strategy pattern for a text compositing algorithm, then you might have classes SimpleLayoutStrategy or TeXLayoutStrategy. 5. Define the classes. Declare their interfaces, establish their inheritance relationships, and define the instance variables that represent data and object references. Identify existing classes in your application that the pattern will affect, and modify them accordingly. 6. Define application-specific names for operations in the pattern. Here again, the names generally depend on the application. Use the responsibilities and collaborations associated with each operation as a guide. Also, be consistent in your naming conventions. For example, you might use the "Create-" prefix consistently to denote a factory method. 7. Implement the operations to carry out the responsibilities and collaborations in the pattern. The Implementation section offers hints to guide you in the implementation. The examples in the Sample Code section can help as well. These are just guidelines to get you started. Over time you'll develop your own way of working with design patterns. No discussion of how to use design patterns would be complete without a few words on how not to use them. Design patterns should not be applied indiscriminately. Often they achieve flexibility and variability by introducing additional levels of indirection, and that can complicate a design and/or cost you some performance. A design pattern should only be applied when the flexibility it affords is actually needed. The Consequences sections are most helpful when evaluating a pattern's benefits and liabilities.
1. Which design pattern do you like the most?
It depends on many factors, such as the context, situation,
demand, constraints, and so on. If you know about all the
patterns, you have more options to choose from.
2. Why should developers use design patterns?
They are reusable solutions for software design problems that
appear repeatedly in real-world software development.
3. How are libraries (or frameworks) similar/different from
design patterns?
They are not design patterns. They provide the implementations
that you can use directly in your application. But they can use the
concept of the patterns in those implementations.
4. If no particular pattern is 100% suitable for my problem, how
should I proceed?
An infinite number of problems cannot be solved with a finite
number of patterns, for sure. But if you know these common
patterns and their trade-offs, you can pick a close match. No one
prevents you from using your own pattern for your own problem,
but you have to tackle the risk.
5. What are the differences between class patterns and object
patterns?
In general, class patterns focus on static relationship but object
patterns can focus on dynamic relationships. As name suggests,
class patterns focus on classes and its subclasses and object
patterns focus on the objects relationships.
As per GoF, these patterns can be further differentiated in Table A-1.
6. Can I combine two or more patterns in an application?
Yes. In real-world scenarios, this type of activity is common.
7. Do these patterns depend on a particular programming
language?
Programming languages can play an important role. But the basic
ideas are same, patterns are just like templates and they give you
some idea in advance of how you can solve a particular problem.
In this book, I primarily focused on object-oriented programming
with the concept of reuse. But instead of any object-oriented
programming language, suppose you have chosen some other
language like C. In that case, you may need to think about the core
object-oriented principles such as inheritance, polymorphism,
encapsulation, abstraction, and so on, and how to implement
them. So, the choice of a particular language is always important
because it may have specialized features that can make your life
easier.
8. Do you suggest any general advice before I jump into the
topics?
I always follow the footsteps of my seniors and teachers who are
experts in this field. And the following are general suggestions
from them.
• Program to a supertype(Abstract class/Interface), not an
implementation.
• Prefer composition over inheritance.
• Try to make a loosely coupled system.
• Segregate the code that is likely to vary from the rest of your code.
• Encapsulate what varies.