oop designpatterns

‘Design Principles’
—Alexander Shvets, “Dive Into Design Patterns”

Encapsulate what varies

This principle emphasizes the importance of identifying and isolating aspects of an application that are likely to change, separating them from the stable components.
The analogy of a ship illustrates this concept: just as a ship can be divided into independent compartments to limit damage from underwater mines, a program can be structured into independent modules. This isolation protects the rest of the code from negative impacts when changes occur. By minimizing the effects of changes, you reduce the time spent fixing issues and increase the time available for implementing new features.

  • Encapsulation on a method level
  • Encapsulation on a class level

Program to an Interface, not an Implementation

oop - What does “program to interfaces, not implementations” mean? - Stack Overflow

Interfaces are just contracts or signatures and they don’t know anything about implementations.

Program to an interface, not an implementation. Depend on abstractions, not on concrete classes.

It means that you should try to write your code so it uses an abstraction (abstract class or interface) instead of the implementation directly.


SA03.3 - Factory Method Pattern

👉 AF01.4 - Liskov Substitution Principle

Favor Composition over Inheritance

language agnostic - Prefer composition over inheritance? - Stack Overflow

01/SA/OOP Revisit > Composition

Inheritance Problems

  • A subclass can’t reduce the interface of the superclass.
  • When overriding methods you need to make sure that the new behavior is compatible with base one.
  • Inheritance breaks encapsulation of the superclass.
  • Sub-classes are tightly coupled to super-classes.
  • Trying to reuse code through inheritance can lead to creating parallel inheritance hierarchies.
    Whereas inheritance represents the “is a” relationship between classes (a car is a transport), composition represents the “has a” relationship (a car has an engine).

Diamond Problem in Java - GeeksforGeeks

Inheritance

class Animal {
  speak() {
    console.log("Some generic sound");
  }
}
 
class Dog extends Animal {
  speak() {
    console.log("Woof!");
  }
}
 
class Cat extends Animal {
  speak() {
    console.log("Meow!");
  }
}
 
const dog = new Dog();
dog.speak(); // Woof!
 
const cat = new Cat();
cat.speak(); // Meow!

Composition

// Behavior modules
const speakBark = {
  speak() {
    console.log("Woof!");
  },
};
 
const speakMeow = {
  speak() {
    console.log("Meow!");
  },
};
 
const runFast = {
  run() {
    console.log("Running fast!");
  },
};
 
const swimWell = {
  swim() {
    console.log("Swimming well!");
  },
};
 
// Composing objects with behaviors
class Animal {
  constructor(name, behaviors) {
    this.name = name;
    Object.assign(this, behaviors);
  }
}
 
const dog = new Animal("Dog", { ...speakBark, ...runFast });
dog.speak(); // Woof!
dog.run();   // Running fast!
 
const cat = new Animal("Cat", { ...speakMeow });
cat.speak(); // Meow!