/design-patterns

Object Oriented Design Patterns

Primary LanguageJava

  • Object-Oriented Design

    • Abstraction

      • Only relevant, client tailored API is exposed to clients

    • Polymorphism

      • Dynamic Polymorphism: Method changes behavior at runtime

      • Static polymorphism: Method overloading

    • Inheritance

      • Reusing parent class functionality

    • Encapsulation

      • Hiding information and keeping related functionality together

      • Encapsulation refers to the idea that objects should manage their own behavior and state, so that their collaborators need not concern themselves with the object’s inner workings

    • Composition, Aggregation

      • Instead of inheritance, composition uses the object to achieve code reuse

      • Aggregation: Relation where A has B and B can exist without A

      • Composition: Relation where A has B and B can NOT exist without A

  • SOLID

    • Single responsibility principle

      • Classes should aim for high cohesiveness

      • Cohesion is a measure of how closely a class or a module supports a single purpose or responsibility.

    • Open Closed Principle

      • Should be open for extension, but closed for modification

      • Classes should be closed for modification but open for extension

    • Liskov Substitution Principle

      • Subtypes must be substitutable for their base types

    • Interface Segregation Principle

      • clients should not be forced to depend on methods that they do not use

    • Dependency Inversion Principle

  • Depend upon abstractions. Do not depend upon concrete classes.

  • High-level components should not depend on our low-level components, rather, they should both depend on abstractions.

  • Abstractions should not depend on details. Details should depend upon abstractions

  • YAGNI

    • You ain’t going to need it.

    • You don’t need it now.

      • Don’t add new functionality until its necessary.

  • KISS

    • Keep it simple stud

  • DRY

    • Don’t repeat yourself

  • OverEngineering

    • Avoid adding those extra features, safety, bells and whistles your customers don’t care about

  • Encapsulate what varies

    • Parts of code that changes together, stays together

    • Separate out parts of code that vary or change from those that remain the same.

  • Favor Composition over inheritance

  • Code to an interface and not against a concrete implementation

  • Encapsulate behaviors

  • Don’t call us we will call you

  • Components are loosely coupled and talk to each other over a well-defined API

  • Fine line between complexity and understandability vs Flexible & Extensible

  • Boys Scout Rule

    • Leave your code better than you found it

  • Broken window Theory

    • Fix the bad code as soon as possible before it encourages other to pile on more.

  • Explicit Dependencies (Constructor Injection/ Method Parameters)

    • Define explicit dependencies on collaborator before creating object or calling method

  • Hollywood Principle

    • Don’t Call Us, We’ll Call You.

    • Polling vs event

  • Tell-Don’t-Ask

    • It is better to issue an object a command do perform some operation or logic, rather than to query its state and then take some action as a result

  • Decouple client code from the concrete classes

  • Advantages

    • Unlike constructors, they have names. Readability improvement

    • Unlike constructors, they are not required to create new objects. Useful in controlling object creation e.g. singleton, flyweight

    • Unlike constructors, they can return an object of any subtype of their return type

    • Class of the returned object can vary from call to cal as a function of input param

  • Disadvantages:

    • Classes only providing factories and w/o public or protected constructors, can not be subclassed

    • hard to notice

  • e.g. java.util.Calendar.getInstance()

  • Used to build complex objects

  • Build objects with a mix of required and non-required parameters

  • e.g. StringBuilder (loosely compared). any object creation where we create object step by step, DocumentBuilder

  • Use the Prototype Pattern when creating an instance of a given class is either expensive or complicated.

  • Create new objects by copying existing objects. The object whose copies are made is called the prototype

  • Creating new objects is more expensive than copying existing objects

  • Think about shallow vs deep copy

  • e.g. clone method exposed by Object class

  • Only one object is created in JVM

  • Think about cost of creation and use lazy or eager initialization

  • Think about single threaded vs multi threaded environment

  • e.g. java.lang.Runtime, java.awt.Desktop

  • This Pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.

  • factory of factories

  • Allow interoperability

  • Allows varying abstractions as well as implementations

  • Decouples an implementation so that it is not bound permanently to an interface

  • Abstraction and implementation can be extended independently

  • Changes to the concrete abstraction classes don’t affect the client

  • Represents hierarchical tree like relation

  • Composite and leaf

  • The composite pattern is meant to allow treating individual objects and compositions of objects, or “composites” in the same way.

  • A wrapper on the class to enhance or extend the behavior of an object dynamically

  • Decouple client from complex subsystem of components

  • Simplifies interface

  • Facade deals with interfaces, not implementation.

  • Hide internal complexity behind a single interface that appears simple on the outside

  • The term comes from boxing and stands for a fighter who weighs less than 111 lbs.

  • Sharing state among many fine-grained objects for efficiency.

  • Centralizes state for many “virtual” objects into a single location.

  • Memory saving and Object explosion is avoided by sharing intrinsic state and extrinsic state is calculated

  • Reduces the number of object instances at runtime, saving memory.

  • Proxies control and manage access to real object (think of Paralegal and Lawyer)

  • The Decorator Pattern adds behavior to an object, while Proxy controls access.

  • Remote Proxy

    • Local representative for an object that lives in a different jvm

  • Virtual Proxy:

    • Representative for an object that may be expensive to create

    • Defers the creation of expensive object until its needed

    • Acts as a surrogate for the object before and while it is being created

  • e.g. java.rmi.* package

  • Use the Memento Pattern when you need to be able to return an object to one of its previous states.

  • e.g. java.io.Serializable

  • The State Pattern allows an object to alter its behavior when its internal state changes.

  • Encapsulate state based behavior and delegate behavior to the current state

  • The object will appear to change its class

  • With the State Pattern, we have a set of behaviors encapsulated in state objects; at any time the context is delegating to one of those states.

  • Exhibit different behaviors in different states

  • Encapsulate interchangeable behaviors and use delegation to decide which behavior to use

  • e.g. custom comparator can be passed to this Collections.sort(list,comparator)

  • Subclasses decide how to implement steps in the algorithm

  • Allows subclasses to define parts of an algorithm without modifying the overall structure or steps of the algorithm

  • Allows you to add operations to a composite/object hierarchy structure without changing the structure itself.

  • Adding new operations is relatively easy.

  • The code for operations performed by the Visitor is centralized.

  • Use the Mediator Pattern to centralize complex communications and control between related objects.

  • Components do not need to know about each other

  • They only talk to a mediator

  • Simplifies maintenance of the system by centralizing control logic.

  • A one-to-many dependency between objects so that when one object changes state all the dependents are notified

  • Publish-subscribe model where subscribers get notified when publisher notifies

  • Allows traversal through a aggregate or a collection without exposing its internal details.

  • The main idea of the Iterator pattern is to extract the traversal behavior of a collection into a separate object called an iterator

  • The Command Pattern allows us to decouple the requester of an action from the object that actually performs the action.

  • Encapsulates a request as an object

  • A command object encapsulates a request to do something (like turn on a light) on a specific object (say, the living room light object)

  • Use when you want to give more than one object a chance to handle a request.

  • Decouples the sender of the request and its receivers.

  • Each receiver contains reference to next receiver.

  • Each handler in turn examines a request and either handles it or passes it on to the next object in the chain

  • e.g. javax.servlet.Filter.doFilter method or mouseclick events on webpage