OOP
General Concepts
- Object: A set of data (fields and properties of an object) taht is physically located in the computer's memory.
- Encapsulation: Class and separating its internal representation from the external.
- Dynamic Binding: which method should be used is decided in runtime.
- Method Overloading: allows multiple methods with the same name but different parameters.
- Method Overriding: changes the behavior of an inherited method.
- Protected Access Modifier: It should only used when accessing from same package.
- Pritive Type: int, byte, long, float, short, char, boolan
- This are stored in stack, while class are stored in heap.
- SOILD
- S – Single Responsibility Principle (SRP)
- A class should have only one reason to change.
- O – Open/Closed Principle (OCP)
- Software entities should be open for extension but closed for modification.
- L – Liskov Substitution Principle (LSP)
- I – Interface Segregation Principle (ISP)
- D – Dependency Inversion Principle (DIP)
- High-level modules should not depend on low-level modules; both should depend on abstractions.
- S – Single Responsibility Principle (SRP)
Object-oriented Architecture
- DRY: Don't Repeat Yourself
- KISS: Keep It Simple, Stupid
- YAGNI:You Aren't Gonna Need It
- GoF Pattens: Gang Of Four design Pattens
Patterns
Creational Patterns
Singleton
.javaclass Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } public void printSometing() { System.out.println("Hello World"); } public static void main(String[] args) { var single = Singleton.getInstance(); single.printSometing(); } }
Prototype
.javainterface PrototypeInterface { PrototypeInterface clone(); } class Prototype { public String name; Prototype() {} Prototype(Prototype proto) { this.name = proto.name; } public void setName(String name) { this.name = name; } public Prototype clone() { return new Prototype(this); } public static void main(String[] args) { var proto1 = new Prototype(); proto1.setName("Jone"); System.out.println(proto1.name); var proto2 = proto1.clone(); System.out.println(proto2.name); } }
Factory
.javainterface Product {} class Product1 implements Product { Product1() { System.out.println("Product1 is created."); } } class Product2 implements Product { Product2() { System.out.println("Product2 is created."); } } class Factory { public Product createProduct(int num) { if (num == 1) { return new Product1(); } else { return new Product2(); } } public static void main(String[] args) { var factory = new Factory(); var product = new Factory().createProduct(1); } }
Builder
.javapublic class Build { private String pkg; private int size; private Build(BuildBuilder builder) { this.pkg = builder.pkg; this.size = builder.size; } public void print() { System.out.printf( "Pkg: %s, Size: %d\n", this.pkg, this.size ); } public static class BuildBuilder { private String pkg; private int size; public BuildBuilder addPkg(String pkg) { this.pkg = pkg; return this; } public BuildBuilder addSize(int size) { this.size = size; return this; } public Build build() { return new Build(this); } } public static void main(String[] args) { var build = new Build.BuildBuilder().addPkg("Product").addSize(100).build(); build.print(); } }
Structural Patterns
Proxy
.javapublic interface Pattern { public void create(); } public class Original implements Pattern { @Override public void create() { System.out.println("Created Orignal Proxy"); } } public class Proxy implements Pattern { protected Original og = new Original(); @Override public void create() { og.create(); } public static void main(String[] args) { var proxy = new Proxy(); proxy.create(); } }
Decorator
.javapublic interface Pattern { public void create(); } class OriginalPattern implements Pattern { @Override public void create() { System.out.println("Created Orignal Pattern"); } } class PatternDecorator implements Pattern { private Pattern pattern; PatternDecorator(Pattern pattern) { this.pattern = pattern; } @Override public void create() { this.pattern.create(); } } class DifferentPattern extends PatternDecorator { DifferentPattern(Pattern pattern) { super(pattern); } @Override public void create() { super.create(); System.out.println("Decorated Orignal Pattern"); } } class Main { public static void main(String[] args) { var ogPattern = new OriginalPattern(); var decoPattern = new DifferentPattern(ogPattern); decoPattern.create(); } }
Adaptor
.javaclass OldAdaptor { void oldPrint() { System.out.println("Old Adaptor"); } } interface Adaptor { public void newPrint(); } class NewAdaptor implements Adaptor { OldAdaptor oldAdaptor; NewAdaptor(OldAdaptor oldAdaptor) { this.oldAdaptor = oldAdaptor; } @Override public void newPrint() { this.oldAdaptor.oldPrint(); } } class Main { public static void main(String[] args) { var oldAdaptor = new OldAdaptor(); var newAdaptor = new NewAdaptor(oldAdaptor); newAdaptor.newPrint(); } }
Facade
.javaclass Real1 { void create() { System.out.println("Created Real1"); } } class Real2 { void create() { System.out.println("Created Real2"); } } class Facade { Real1 real1; Real2 real2; Facade() { real1 = new Real1(); real2 = new Real2(); } void createReal1() { real1.create(); } void createReal2() { real2.create(); } } class Main { public static void main(String[] args) { var facade = new Facade(); facade.createReal1(); facade.createReal2(); } }
Bridge: Two classes can be devlop separate
Composite
.javainterface Composite { public void create(); } class Item implements Composite { int id; Item(int id) { this.id = id; } @Override public void create() { System.out.println("Created Item" + this.id); } } class Container implements Composite { List<Composite> items = new ArrayList<>(); void addItem(Composite item) { items.add(item); } void runItems() { for (Composite item: items) { item.create(); } } @Override public void create() { System.out.println("Created Container"); } public static void main(String[] args) { var container = new Container(); container.create(); container.addItem(new Item(1)); container.addItem(new Item(2)); container.runItems(); } }
Behavioral
Strategy
.javainterface Strategy { public int calculate(int a, int b); } class Algorithm1 implements Strategy { @Override public int calculate(int a, int b) { return a + b; } } class Algorithm2 implements Strategy { @Override public int calculate(int a, int b) { return a - b; } } class StrategyRun { Strategy algo; StrategyRun(Strategy strategy) { this.algo = strategy; } void print(int a, int b) { System.out.printf( "Run starategy of a = %d & b = %d is %d\n", a, b, this.algo.calculate(a, b) ); } public static void main(String[] args) { var run = new StrategyRun(new Algorithm1()); run.print(10, 10); run = new StrategyRun(new Algorithm2()); run.print(10, 10); } }
Command Pattern: It turns a request or method call into stand-alone object.
Template Pattern: It defines skeleton of the algorithm.
Iterator Pattern: It makes iterable object which
.hasNext(), .next()
methods.Chain of Responsiblity: Allows you to pass a request along a chain of handlers.
- Interface: Validator
- Class: ArrayList
- UppercaseValidator
- LowerValidator
- SpecialValidator
- Handler: CheckPassword
Visitor Pattern: allows you to add new operations to existing classes without modifying their structure.
Observer Pattern: defines a one-to-many dependency between objects
Interpreter Pattern: defines a grammar for a language and provides an interpreter to evaluate expression.
State Pattern: Object changes its behavior when its internal state changes.
.javaclass State { private int value = 0; public void increment() { value++; System.out.println("Value: " + value); } public void decrement() { value--; System.out.println("Value: " + value); } public Memento save() { return new Memento(this.value); } public void restore(Memento memento) { this.value = memento.getValue(); System.out.println("Restored: " + value); } public static void main(String[] args) { var state = new State(); } }
Mediator Pattern: It centralizes communication between multiple object
.javaclass Memento { private final int value; Memento(int value) { this.value = value; } public int getValue() { return this.value; } } class State { private int value = 0; public void increment() { value++; System.out.println("Value: " + value); } public void decrement() { value--; System.out.println("Value: " + value); } public Memento save() { return new Memento(this.value); } public void restore(Memento memento) { this.value = memento.getValue(); System.out.println("Restored: " + value); } }