-
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
-
Head First Design Patterns Book by Elisabeth Freeman and Kathy Sierra