Design Pattern

OOP Concepts in Java

  • Encapsulation

    • Revealing class members to different scopes accordingly.

  • Abstraction

    • Seeing a high level concept as an Entity, instead of seeing a bunch of components.

  • Inheritance

    • For code reusability, sub-classes extend properties and behaviors from parent class.

  • Polymorphism

    • One name, many forms.

      • Overriding

      • Overloading

OO Design Principles (SOLID) by Robert Martin

  • SRP (Single Responsibility Principle)

  • OCP (Open Closed Principle)

    • Open for extension, but closed for modification. (Considering extenstion to change rather than modification.)

  • LSP (Liskov Substitution Principle)

    • Functions that use references to base classes must be able to use objects of the derived class without knowing it.

    • When implementing sub-class, should consider if a method referencing parent class occurs unexpected result.

  • ISP (Interface Segregation Principle)

    • Interfaces containing methods that are not specific to it are called polluted or fat interfaces. We should avoid them.

  • DIP (Dependency Inversion Principle)

    • Definition:

      • High-level modules should not depend on low-level modules. Both of them should depend on abstractions.

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

    • IoC is an implementation of DIP. And DI (Dependency Injection) is a way of IoC.

    • 3 ways of DI: with constructor (recommended), with setter, with property.

OO Design Patterns

Structural Type

These design patterns concern class and object composition. Concept of inheritance is used to compose interfaces and define ways to compose objects to obtain new functionalities.

  • Facade (外觀) Pattern

    • Purpose: To simplify details for clients (make a black-box for clients to know / worry less) by implementing a facade class with multiple functionalities.

  • Adapter Pattern

    • Purpose: To grant an object to have functionalities of another class.

    • How: Creating an adapter class to accept adaptee object and implement methods of target class.

  • Decorator Pattern

    • Purpose: To add more functionalities to a class, but keep signature intact. The decorated class is the descendant of original class (A different style of Adapter.)

    • Ex: Wrapper class, Java I/O.

  • Proxy Pattern

    • Purpose:

      • To control and to access another object (which may be expensive or impossible to duplicate) behind the scenes. Ex: caching.

      • To provide additional logic, extra functionality to target object. Ex: Spring AOP.

  • Composite (合成) Pattern

    • Purpose: When an object that contains group of its own objects, have identical processes to them.

    • How: Create a tree hierarchy structure for objects to process similar operation by implementing the same interface.

  • Flyweight (享元) Pattern

    • Purpose: To reduce the number of objects created and to decrease memory footprint and increase performance.

Behavioral Type

These design patterns are specifically concerned with communication between objects.

  • Observer Pattern

    • Purpose: To decouple subject from observers (depenedent objects).

    • How: Invoking the notify method of the subject object to trigger update method of of observer objects.

  • Command Pattern

    • Purpose:

      • To encapsulate all the data required for performing a given action into an Command object.

      • To decouple objects that produce the commands (Client) from their consumers (Invoker). Known as the producer-consumer pattern.

      • In some cases, the invoker also stores and queues commands, aside from executing them. This is useful for implementing some additional features, such as macro recording or undo and redo functionality.

    • How: Making a class action into a concrete Command class which implements a Command interface with an execute method.

    • Ex: job queue, threadpool, rule engine

  • Strategy Pattern

    • Purpose:

      • Making an action (algorithm) into an interface and be implemented, so the "Context" can make the action differently at run time.

    • Usage:

      • If many "Context" classes shares 2+ types of actions, this prevent repeated implementations among "Context" classes.

  • Template Pattern

    • Purpose: To keep operation control (template method) in parent class, but let sub-class to define detail of methods in the operation.

    • How: An abstract class defining operations with a template method set to be final, so that it cannot be overridden by sub-class. However the template method uses some abstract methods that be implemented by sub-class.

  • Iterator Pattern

    • Purpose: To access the elements of a collection object in sequential manner without any need to know its underlying implementation.

Creational Type

  • Factory Pattern

    • Purpose: To decouple product instantiation from client and product.

    • How: 4 Types as below:

      • Simple Factory

        • How: Move the part of object instantiation to a class. It's more like a coding habbit than a pattern.

      • Static Factory

        • How: Almost the same with Simple Factory, except using static modifier.

        • Advantage: The static factory can do the whole control about to create, to return an available one object or an exception when the total objects need to limited, like DB connection pool.

        • Ex: Message message = MessageFactory.getMessage(session);

      • Factory

        • How: Creating an abstract creator class and an abstract product class with abstract createProduct method. Then implement concrete product and creator classes.

      • Abstract Factory

        • To build up a family of products (or attributes)! An abstract class to describe product attributes. let sub-class to implement all detailed attributes.

  • Builder Pattern

    • Purpose: To build a complex object using simple objects and using a step by step approach.

    • Reference:

      • Builder often builds a Composite.

      • 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.

  • Singleton Pattern

    • Purpose: Making sure there's only one object of the class at one time.

    • How: Through public static method to return private unique instance. 3 types as below:

      • Eager instantiation

        • New instance directly when declaring the unique object.

      • Lazy instantiation

        • Add synchronized modifier to the getInstance method and check if the unique object is null to create the instance or not.

        • The performance of synchronized method may down to 1/100.

      • Double-checked locking

        • Code Example:

          // Works with acquire/release semantics for volatile in Java 1.5 and later
          // Broken under Java 1.4 and earlier semantics for volatile
          class Foo {
              private volatile Helper helper;
              public Helper getHelper() {
                  Helper localRef = helper;
                  if (localRef == null) {
                      synchronized (this) {
                          localRef = helper;
                          if (localRef == null) {
                              helper = localRef = new Helper();
                          }
                      }
                  }
                  return localRef;
              }
          
              // other functions and members...
          }
        • Reference: Variable declared as volatile can only be read / write within main memory, not in any cache.

Last updated