Notes on Refactoring to Patterns

  • Replace Constructors with Creation Methods (also known as Static Factory Method) - Use a static or nonstatic method to create instances. For example: TodoStore.createItem(data)
    • If you have too many Creation Methods, you can apply Extract Factory and create a factory. (e.g. if you have a Todo class with 5 methods each to create a different type of todo item, you create a Factory that holds all these creation methods so the intent of the original Todo class is clear).
  • Move Creation Knowledge to Factory When you have too many classes that unnecessarily know how to create instances of a class, you combine all those creational methods to a single Factory class
    • Creation Method - a static or nonstatic method returns an instance of a class
    • Factory - a class that implements one or more Creation Methods
    • Factory Method - "a nonstatic method that returns a base class or interface type and that is implemented in a hierarchy to enable polymorphic creation" (p 71). https://en.wikipedia.org/wiki/Factory_method_pattern
    • Abstract Factory - "an interface for creating families of related or dependent objects without specifying their concrete classes" (Design Patterns, 87). https://en.wikipedia.org/wiki/Abstract_factory_pattern#Pseudocode
      • Every Abstract Factory is a Factory but not conversely.
  • Encapsulate Composite with Builder Simplify the creation of a composite (e.g. a parent DOM node with a couple of children DOM nodes) by using a Builder to deal with the complex details.
    • If you have a class with many options, then you would need a lot of constructors to cover the combinations. So Instead, you use a Builder factory which allows you to set the options one by one. https://en.wikipedia.org/wiki/Builder_pattern
    • A Builder class will have one method to actually get the instance which is called as the last step to the Builder.
  • Compose Method Turn a long block / function definition into a series of well-named small-bite function calls.
  • Replace Conditional Logic with Strategy - Instead of using conditional logic to determine which algorithm to use - you delegate to a strategy instance.
    • Strategy Pattern has the program select the appropriate strategy at run time. Only use Strategy pattern when you are going to change the algorithms a lot. Javascript example at: http://www.dofactory.com/javascript/strategy-design-pattern
      • defines a family of algorithms,
      • encapsulates each algorithm, and
      • makes the algorithms interchangeable within that family.
  • Replace State-Altering Conditionals with State - Similar to Strategy but with a different intent. State is concerned with WHAT you can do and Strategy is considered with HOW you do something
    • Extract class to a State Class
    • Copy each method that modifies state in the host class to the new State class
    • Create subclass for each type of state
    • Copy each method for the subclass state and simplify the method from conditionals
    • Repeat for each state subclass and method that modifies state
  • Replace Conditional with Polymorphism
    • If your host class (the context) has subclasses, and the different subclasses matches the variations of algorithms then this is a good choice for refactoring (p. 130)
  • Replace Type Code with Subclasses - If the conditions to select the variations of the algorithm is based on type code, this is the preferred refactoring. 
  • Replace Conditional Dispatcher with Command - Command pattern separates who requests a command and who executes the command.
    • Use this when:
      • You need to dynamically modify the conditional logic for dispatching
      • You have to scroll a lot to understand the conditional & dispatching actions
  • Misc notes:
    • Abstract vs. concrete: abstract type is a type in a nominative type system which cannot be instantiated directly
    • Nominal vs. structural: nominal (Java) vs structural / duck typing (Typescript)
    • Template method pattern "is a behavioral design pattern that defines the program skeleton of analgorithm in a method, called template method, which defers some steps to subclasses" (source: Wikipedia).  first a class is created that provides the basic steps of an algorithm design. These steps are implemented using abstract methods. Later on, subclasses change the abstract methods to implement real actions. Thus the general algorithm is saved in one place but the concrete steps may be changed by the subclasses.
    • Algorithm is just a step-by-step of instructions
    • invariant (or standard), and which are variant (or customizable)
    • Composite pattern is constructing a tree-like structure of objects (e.g. a parent DOM node with two DOM child elements)

Creational Patterns: creating instances

Structural Patterns: class and object composition

Behavioral Patterns: communication between objects

Note: Quotes are from the book Refactoring to Patterns by Joshua Kerievsky.

Highly recommend this resource on Design Patterns: https://sourcemaking.com/design_patterns

Design patterns are a language weakness: http://www.norvig.com/design-patterns/design-patterns.pdf

Pattern hierarchy: http://stackoverflow.com/questions/3883692/strategy-pattern-vs-command-pattern

views