Giter Club home page Giter Club logo

design-pattern-assignment's Introduction

SOLID Principles

1. Liskov Substitution Principle

If S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program.

Here subtyping means Inheritance

LSP image

  • When a child Class cannot perform the same actions as its parent Class, this can cause bugs.
  • If you have a Class and create another Class from it, it becomes a parent and the new Class becomes a child. The child Class should be able to do everything the parent Class can do. This process is called Inheritance.
  • The child Class should be able to process the same requests and deliver the same result as the parent Class or it could deliver a result that is of the same type.

The picture shows that the parent Class delivers Coffee(it could be any type of coffee). It is acceptable for the child Class to deliver Cappucino because it is a specific type of Coffee, but it is NOT acceptable to deliver Water.

NOTE:- If the child Class doesn’t meet these requirements, it means the child Class is changed completely and violates this principle.

Let's take A Look n Code

1. Trait CoffeeMachine.scala

Make a trait so that we can overide is methods

trait CoffeeMachine {
  def serveCoffee(): Unit
}

2. BasicCoffeeMachine.scala

  • BasicCoffeeMachine class extended with trait and defines it own method and override serveCoffee()
  • In this way our subtype is replaced without disturbing desirable properties of program.
class BasicCoffeeMachine extends CoffeeMachine {
  val coffee="Powdered"

  override def serveCoffee(): Unit = {
    val cup = brewFilterCoffee(coffee)
    println("Here is your " + cup)
  }
  def brewFilterCoffee(coffee:String): String ={
    println("coffee is in " +coffee+" form")
    println("Brewing...")
    "Freshly brewed coffee"
  }
}

3. PremiumCoffeemachine.scala

  • PremiumCoffeeMachine class extended with trait and defines it own method and override serveCoffee()
class PremiumCoffeeMachine extends CoffeeMachine {
  val coffee = "Beans"

  override def serveCoffee(): Unit = {
    val cup = brewFilterCoffee(coffee)
    println("Here is your "+cup)
  }

  def brewFilterCoffee(coffee:String): String ={
    println("coffee is in " +coffee+" form")
    println("Grinding beans")
    println("Brewing... Filtering...")
    "Freshly brewed premium Latte` coffee"
  }
}

Main method

object Main extends App{
  val basic = new BasicCoffeeMachine()
  val premium = new PremiumCoffeeMachine
  premium.serveCoffee()
  basic.serveCoffee()
}

Output

coffee is in Beans form
Grinding beans
Brewing... Filtering...
Here is your Freshly brewed premium Latte` coffee
coffee is in Powdered form
Brewing...
Here is your Freshly brewed coffee

Goal os LSP

This principle aims to enforce consistency so that the parent Class or its child Class can be used in the same way without any errors.

2. Interface Segregation principle

Clients should not be forced to depend on methods that they do not use.

ISP image Notes:-

  • When a Class is required to perform actions that are not useful, it is wasteful and may produce unexpected bugs if the Class does not have the ability to perform those actions.

  • A Class should perform only actions that are needed to fulfil its role. Any other action should be removed completely or moved somewhere else if it might be used by another Class in the future.

Code implementation of ISP

1. Cashier.scala

Cashier.scala is trait

trait Cashier {
  def makeBill(): Int
}

2. CoffeeMaker.scala

CoffeeMaker is a trait

trait CoffeeMaker {
  def makeCoffee(): Unit
}

3. CoffeeServer.scala

CoffeeServer.scala is a trait

trait CoffeeServer {
  def serveCoffee(): Unit
}

4. DrinkCoffee.scala

DrinkCoffee.scala is a trait

trait DrinkCoffee {
  def drinkCoffee(): Unit
}

5. CoffeeShop.scala

In this we made 3 classes to perform task related to coffee shop only that is make coffee, Serve the coffee, Billing Extends those classes with an respective interface for example: class Server extends CoffeeServer

class CoffeeShop extends CoffeeMaker {
  override def makeCoffee(): Unit = {
    println("Making coffee... ")
  }
}

class Server extends CoffeeServer{
  override def serveCoffee(): Unit = {
    println("Serve coffee")
  }
}

class Bill(amount:Int) extends Cashier{
  override def makeBill(): Int = {
    println("Making Bill...")
    var price = amount
    price
  }
}

6. Customer.scala

In this class we defined methods only related to customer We extends this class with interface DrinkCoffee and a method is defined payBill()

class Customer extends DrinkCoffee {
  override def drinkCoffee(): Unit = {
    println("drinking coffee")
  }
  def payBill(bill:Int): Unit ={
    println("Bill paid of "+bill)
  }
}

Main Method

object Main extends App{
  val rahul = new Customer
  val cup = new CoffeeShop
  cup.makeCoffee()
  val server = new Server()
  server.serveCoffee()
  rahul.drinkCoffee()
  val bill = new Bill(100)
  rahul.payBill(bill.makeBill())
}

Output

Making coffee... 
Serve coffee
drinking coffee
Making Bill...
Bill paid of 100

Goal of ISP

This principle aims at splitting a set of actions into smaller sets so that a Class executes ONLY the set of actions it requires.

3. Dependency Inversion

  • High-level modules should not depend on low-level modules. Both should depend on the abstraction.
  • Abstractions should not depend on details. Details should depend on abstractions.

DIP image

  • High-level Module(or Class): Class that executes an action with a tool.
  • Low-level Module (or Class): The tool that is needed to execute the action
  • Abstraction: Represents an interface that connects the two Classes

Principle

This principle says a Class should not be fused with the tool it uses to execute an action. Rather, it should be fused to the interface that will allow the tool to connect to the Class.

It also says that both the Class and the interface should not know how the tool works. However, the tool needs to meet the specification of the interface.

Code implementation of DIP

Coffeemaker.scala

Coffeemaker.scala is a trait

trait CoffeeMaker {
  def makeCoffee(): String
}

Cappuccino.scala

This class extends CoffeeMaker trait to make cappuccino coffee

class Cappuccino extends CoffeeMaker {
  override def makeCoffee(): String = {
    "Makes a Cappuccino"
  }
}

Latte.scala

This class extends CoffeeMaker trait to make latte coffee

class Latte extends CoffeeMaker {
  override def makeCoffee(): String = {
    "Makes a Latte"
  }
}

CoffeeServer.scala

class CoffeeServer {
  def serveCoffee(coffee:CoffeeMaker): Unit ={
    val cup = coffee.makeCoffee()
    println(cup)
  }
}

main method

object Main extends App{
  val serve = new CoffeeServer
  serve.serveCoffee(new Cappuccino)
  serve.serveCoffee(new Latte)
}

Output

Makes a Cappuccino
Makes a Latte

Goal of DIP

This principle aims at reducing the dependency of a high-level Class on the low-level Class by introducing an interface.

design-pattern-assignment's People

Watchers

Dev Ninja avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.