├── .gitignore
├── README.md
├── pom.xml
└── src
└── main
└── java
└── com
└── techtong
└── solid
├── dip
├── refactored
│ ├── Main.java
│ ├── models
│ │ ├── Customer.java
│ │ └── ShoppingCart.java
│ └── services
│ │ ├── NewCheckoutService.java
│ │ ├── NewSmsService.java
│ │ └── sms
│ │ ├── GpSmsProvider.java
│ │ ├── RobiSmsProvider.java
│ │ └── SmsProvider.java
└── violation
│ ├── Main.java
│ ├── models
│ ├── Customer.java
│ └── ShoppingCart.java
│ └── services
│ ├── CheckoutService.java
│ └── SmsService.java
├── isp
├── refactored
│ ├── Main.java
│ └── account
│ │ ├── BaseAccount.java
│ │ ├── InternationalAmountTransferable.java
│ │ ├── RemittanceSavingsAccount.java
│ │ ├── SavingsAccount.java
│ │ └── StudentAccount.java
└── violation
│ ├── Main.java
│ └── account
│ ├── RemittanceSavingsAccount.java
│ ├── SavingsAccount.java
│ └── StudentAccount.java
├── lsp
├── refactored
│ ├── Main.java
│ └── model
│ │ ├── ContractEmployee.java
│ │ ├── Employee.java
│ │ ├── EmployeeBonusEligible.java
│ │ ├── IEmployee.java
│ │ ├── PermanentEmployee.java
│ │ └── TemporaryEmployee.java
└── violation
│ ├── Main.java
│ └── model
│ ├── ContractEmployee.java
│ ├── Employee.java
│ ├── PermanentEmployee.java
│ └── TemporaryEmployee.java
├── ocp
├── OCP.java
├── refactored
│ ├── DecentKitchenService.java
│ ├── FoodPreparer.java
│ └── models
│ │ ├── BakedFood.java
│ │ ├── FoodItem.java
│ │ ├── FriedFood.java
│ │ ├── GrilledFood.java
│ │ └── SauteedFood.java
└── violation
│ ├── BadKitchenService.java
│ └── models
│ ├── FoodItem.java
│ ├── FriedFood.java
│ └── GrilledFood.java
└── srp
├── refactored
├── Customer.java
├── Item.java
├── Main.java
├── logger
│ ├── ConsoleLogger.java
│ ├── FileLogger.java
│ └── Logger.java
└── pricecalculation
│ ├── ItemPriceCalculationService.java
│ └── TaxCalculationService.java
└── violation
├── Customer.java
├── Item.java
└── Main.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 |
3 | *.iml
4 |
5 | # Compiled class file
6 | *.class
7 |
8 | # Log file
9 | *.log
10 |
11 | # BlueJ files
12 | *.ctxt
13 |
14 | # Mobile Tools for Java (J2ME)
15 | .mtj.tmp/
16 |
17 | # Package Files #
18 | *.jar
19 | *.war
20 | *.nar
21 | *.ear
22 | *.zip
23 | *.tar.gz
24 | *.rar
25 |
26 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
27 | hs_err_pid*
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Solid Principles
2 |
3 | This repository contains codes for the first deep dive series on Solid Principles.
4 |
5 | - Code related to a principle has its own package under solid.
6 | - Principle violated code will be under the violated package, and refactored one will under the refactored package.
7 | - If you feel we could do better in refactoring, don't forget to create a PR with your changes
8 | - If you have any feedback, please email us at techtongbd@gmail.com
9 |
10 | License
11 | ----
12 |
13 | MIT
14 |
15 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.techtong
8 | solid-principles
9 | 1.0.0
10 |
11 |
12 |
13 | org.apache.maven.plugins
14 | maven-compiler-plugin
15 |
16 | 10
17 | 10
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/refactored/Main.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.refactored;
2 |
3 | import com.techtong.solid.dip.refactored.models.Customer;
4 | import com.techtong.solid.dip.refactored.models.ShoppingCart;
5 | import com.techtong.solid.dip.refactored.services.NewCheckoutService;
6 | import com.techtong.solid.dip.refactored.services.NewSmsService;
7 | import com.techtong.solid.dip.refactored.services.sms.GpSmsProvider;
8 | import com.techtong.solid.dip.refactored.services.sms.RobiSmsProvider;
9 | import com.techtong.solid.dip.refactored.services.sms.SmsProvider;
10 |
11 | public class Main {
12 | public static void main(String[] args) {
13 | Customer customer = new Customer("Sabbir Siddiqui", "01717111111");
14 | ShoppingCart shoppingCart = new ShoppingCart(1200, customer);
15 |
16 | SmsProvider smsProvider = new RobiSmsProvider();
17 | // SmsProvider smsProvider = new GpSmsProvider();
18 | NewSmsService smsService = new NewSmsService(smsProvider);
19 | NewCheckoutService checkoutService = new NewCheckoutService(smsService);
20 |
21 | checkoutService.checkout(shoppingCart);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/refactored/models/Customer.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.refactored.models;
2 |
3 | public class Customer {
4 | private String fullName;
5 | private String phoneNumber;
6 |
7 | public Customer(String fullName, String phoneNumber) {
8 | this.fullName = fullName;
9 | this.phoneNumber = phoneNumber;
10 | }
11 |
12 | public String getFullName() {
13 | return fullName;
14 | }
15 |
16 | public void setFullName(String fullName) {
17 | this.fullName = fullName;
18 | }
19 |
20 | public String getPhoneNumber() {
21 | return phoneNumber;
22 | }
23 |
24 | public void setPhoneNumber(String phoneNumber) {
25 | this.phoneNumber = phoneNumber;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/refactored/models/ShoppingCart.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.refactored.models;
2 |
3 | public class ShoppingCart {
4 | private double totalAmount;
5 | private Customer customer;
6 |
7 | public ShoppingCart(double totalAmount, Customer customer) {
8 | this.totalAmount = totalAmount;
9 | this.customer = customer;
10 | }
11 |
12 | public double getTotalAmount() {
13 | return totalAmount;
14 | }
15 |
16 | public void setTotalAmount(double totalAmount) {
17 | this.totalAmount = totalAmount;
18 | }
19 |
20 | public Customer getCustomer() {
21 | return customer;
22 | }
23 |
24 | public void setCustomer(Customer customer) {
25 | this.customer = customer;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/refactored/services/NewCheckoutService.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.refactored.services;
2 |
3 | import com.techtong.solid.dip.refactored.models.ShoppingCart;
4 |
5 | public class NewCheckoutService {
6 | private final NewSmsService newSmsService;
7 |
8 | public NewCheckoutService(NewSmsService newSmsService) {
9 | this.newSmsService = newSmsService;
10 | }
11 |
12 | private void sendConfirmationSms(ShoppingCart shoppingCart) {
13 | final String message = "Thank you, " + shoppingCart.getCustomer().getFullName() + " for shopping at our store." +
14 | "\nYour order of total BDT " + shoppingCart.getTotalAmount() + " has been confirmed.";
15 |
16 | newSmsService.sendSms(message, shoppingCart.getCustomer().getPhoneNumber());
17 | }
18 |
19 | public void checkout(ShoppingCart shoppingCart) {
20 | // do some other stuff here
21 | System.out.println("Checking out " + shoppingCart.getCustomer().getFullName());
22 | // send sms
23 | sendConfirmationSms(shoppingCart);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/refactored/services/NewSmsService.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.refactored.services;
2 |
3 | import com.techtong.solid.dip.refactored.services.sms.SmsProvider;
4 |
5 | public class NewSmsService {
6 | private SmsProvider smsProvider;
7 |
8 | public NewSmsService(SmsProvider smsProvider) {
9 | this.smsProvider = smsProvider;
10 | }
11 |
12 | void sendSms(String text, String phoneNumber) {
13 | smsProvider.sendSms(phoneNumber, text);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/refactored/services/sms/GpSmsProvider.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.refactored.services.sms;
2 |
3 | public class GpSmsProvider implements SmsProvider {
4 | @Override
5 | public void sendSms(String phoneNumber, String text) {
6 | System.out.println("Sending SMS via GP:");
7 | System.out.println("----> Receiver: " + phoneNumber);
8 | System.out.println("----> Text:\n" + text);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/refactored/services/sms/RobiSmsProvider.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.refactored.services.sms;
2 |
3 | public class RobiSmsProvider implements SmsProvider {
4 | @Override
5 | public void sendSms(String phoneNumber, String text) {
6 | System.out.println("Sending SMS via Robi:");
7 | System.out.println("----> Receiver: " + phoneNumber);
8 | System.out.println("----> Text:\n" + text);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/refactored/services/sms/SmsProvider.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.refactored.services.sms;
2 |
3 | public interface SmsProvider {
4 | void sendSms(String phoneNumber, String text);
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/violation/Main.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.violation;
2 |
3 | import com.techtong.solid.dip.violation.models.Customer;
4 | import com.techtong.solid.dip.violation.models.ShoppingCart;
5 | import com.techtong.solid.dip.violation.services.CheckoutService;
6 |
7 | public class Main {
8 | public static void main(String[] args) {
9 | Customer customer = new Customer("Sabbir Siddiqui", "01717111111");
10 | ShoppingCart shoppingCart = new ShoppingCart(1200, customer);
11 |
12 | CheckoutService checkoutService = new CheckoutService();
13 |
14 | checkoutService.checkout(shoppingCart);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/violation/models/Customer.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.violation.models;
2 |
3 | public class Customer {
4 | private String fullName;
5 | private String phoneNumber;
6 |
7 | public Customer(String fullName, String phoneNumber) {
8 | this.fullName = fullName;
9 | this.phoneNumber = phoneNumber;
10 | }
11 |
12 | public String getFullName() {
13 | return fullName;
14 | }
15 |
16 | public void setFullName(String fullName) {
17 | this.fullName = fullName;
18 | }
19 |
20 | public String getPhoneNumber() {
21 | return phoneNumber;
22 | }
23 |
24 | public void setPhoneNumber(String phoneNumber) {
25 | this.phoneNumber = phoneNumber;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/violation/models/ShoppingCart.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.violation.models;
2 |
3 | public class ShoppingCart {
4 | private double totalAmount;
5 | private Customer customer;
6 |
7 | public ShoppingCart(double totalAmount, Customer customer) {
8 | this.totalAmount = totalAmount;
9 | this.customer = customer;
10 | }
11 |
12 | public double getTotalAmount() {
13 | return totalAmount;
14 | }
15 |
16 | public void setTotalAmount(double totalAmount) {
17 | this.totalAmount = totalAmount;
18 | }
19 |
20 | public Customer getCustomer() {
21 | return customer;
22 | }
23 |
24 | public void setCustomer(Customer customer) {
25 | this.customer = customer;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/violation/services/CheckoutService.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.violation.services;
2 |
3 | import com.techtong.solid.dip.violation.models.ShoppingCart;
4 |
5 | public class CheckoutService {
6 | private final SmsService smsService;
7 |
8 | public CheckoutService() {
9 | this.smsService = new SmsService();
10 | }
11 |
12 | private void sendConfirmationSms(ShoppingCart shoppingCart) {
13 | final String message = "Thank you, " + shoppingCart.getCustomer().getFullName() + " for shopping at our store." +
14 | "\nYour order of total BDT " + shoppingCart.getTotalAmount() + " has been confirmed.";
15 |
16 | smsService.sendSms(message, shoppingCart.getCustomer().getPhoneNumber());
17 | }
18 |
19 | public void checkout(ShoppingCart shoppingCart) {
20 | // do some other stuff here
21 | System.out.println("Checking out " + shoppingCart.getCustomer().getFullName());
22 | // send sms
23 | sendConfirmationSms(shoppingCart);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/dip/violation/services/SmsService.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.dip.violation.services;
2 |
3 | public class SmsService {
4 | void sendSms(String text, String phoneNumber) {
5 | System.out.println("Sending SMS via GP:");
6 | System.out.println("----> Receiver: " + phoneNumber);
7 | System.out.println("----> Text:\n" + text);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/isp/refactored/Main.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.isp.refactored;
2 |
3 |
4 | import com.techtong.solid.isp.refactored.account.RemittanceSavingsAccount;
5 | import com.techtong.solid.isp.refactored.account.StudentAccount;
6 |
7 | public class Main {
8 |
9 | public static void main(String[] args) {
10 |
11 | RemittanceSavingsAccount remittanceSavingsAccount = new RemittanceSavingsAccount(
12 | 1,
13 | "Rahim",
14 | 100,
15 | "Italy");
16 |
17 | remittanceSavingsAccount.creditLocalAmount(100);
18 | remittanceSavingsAccount.creditInternationalAmount(10);
19 |
20 | System.out.println(remittanceSavingsAccount.getBalance());
21 |
22 |
23 | StudentAccount studentAccount = new StudentAccount(
24 | 1,
25 | "Karim",
26 | 100,
27 | "BUET");
28 |
29 | studentAccount.creditLocalAmount(100);
30 |
31 | System.out.println(studentAccount.getBalance());
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/isp/refactored/account/BaseAccount.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.isp.refactored.account;
2 |
3 | public class BaseAccount {
4 | protected int accountId;
5 | protected String accountName;
6 | protected double balance;
7 |
8 | public BaseAccount(int accountId, String accountName, double balance) {
9 | this.accountId = accountId;
10 | this.accountName = accountName;
11 | this.balance = balance;
12 | }
13 |
14 | public double getBalance() {
15 | return balance;
16 | }
17 |
18 | public void setBalance(double balance) {
19 | this.balance = balance;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/isp/refactored/account/InternationalAmountTransferable.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.isp.refactored.account;
2 |
3 | public interface InternationalAmountTransferable {
4 | public void creditInternationalAmount(double amountInUSD);
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/isp/refactored/account/RemittanceSavingsAccount.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.isp.refactored.account;
2 |
3 | public class RemittanceSavingsAccount extends BaseAccount implements SavingsAccount, InternationalAmountTransferable {
4 | private String primarySourceCountry;
5 |
6 | public RemittanceSavingsAccount(int accountId,
7 | String accountName,
8 | double balance,
9 | String primarySourceCountry) {
10 | super(accountId, accountName, balance);
11 | this.primarySourceCountry = primarySourceCountry;
12 | }
13 |
14 | @Override
15 | public double getBalance() {
16 | return this.balance;
17 | }
18 |
19 | @Override
20 | public void creditLocalAmount(double amountInBDT) {
21 | this.balance += amountInBDT;
22 | }
23 |
24 | @Override
25 | public void creditInternationalAmount(double amountInUSD) {
26 | double amountInBDT = amountInUSD * 86;
27 | double incentiveAmount = amountInBDT * 0.02;
28 | this.balance += amountInBDT + incentiveAmount;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/isp/refactored/account/SavingsAccount.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.isp.refactored.account;
2 |
3 | public interface SavingsAccount {
4 | public double getBalance();
5 |
6 | public void creditLocalAmount(double amountInBDT);
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/isp/refactored/account/StudentAccount.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.isp.refactored.account;
2 |
3 | public class StudentAccount extends BaseAccount implements SavingsAccount {
4 | private String institutionName;
5 |
6 | public StudentAccount(int accountId,
7 | String accountName,
8 | double balance,
9 | String institutionName) {
10 | super(accountId, accountName, balance);
11 | this.institutionName = institutionName;
12 | }
13 |
14 | @Override
15 | public void creditLocalAmount(double amountInBDT) {
16 | this.balance += amountInBDT;
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/isp/violation/Main.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.isp.violation;
2 |
3 | import com.techtong.solid.isp.violation.account.RemittanceSavingsAccount;
4 | import com.techtong.solid.isp.violation.account.StudentAccount;
5 |
6 | public class Main {
7 |
8 | public static void main(String[] args) {
9 |
10 | RemittanceSavingsAccount remittanceSavingsAccount = new RemittanceSavingsAccount(
11 | 1,
12 | "Rahim",
13 | 100,
14 | "Italy");
15 |
16 | remittanceSavingsAccount.creditLocalAmount(100);
17 | remittanceSavingsAccount.creditInternationalAmount(10);
18 |
19 | System.out.println(remittanceSavingsAccount.getBalance());
20 |
21 |
22 | StudentAccount studentAccount = new StudentAccount(
23 | 1,
24 | "Karim",
25 | 100,
26 | "BUET");
27 |
28 | studentAccount.creditLocalAmount(100);
29 | studentAccount.creditInternationalAmount(10);
30 |
31 | System.out.println(studentAccount.getBalance());
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/isp/violation/account/RemittanceSavingsAccount.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.isp.violation.account;
2 |
3 | import com.techtong.solid.isp.refactored.account.BaseAccount;
4 |
5 | public class RemittanceSavingsAccount extends BaseAccount implements SavingsAccount {
6 | private String primarySourceCountry;
7 |
8 | public RemittanceSavingsAccount(int accountId,
9 | String accountName,
10 | double balance,
11 | String primarySourceCountry) {
12 | super(accountId, accountName, balance);
13 | this.primarySourceCountry = primarySourceCountry;
14 | }
15 |
16 | @Override
17 | public double getBalance() {
18 | return this.balance;
19 | }
20 |
21 | @Override
22 | public void creditLocalAmount(double amountInBDT) {
23 | this.balance += amountInBDT;
24 | }
25 |
26 | @Override
27 | public void creditInternationalAmount(double amountInUSD) {
28 | double amountInBDT = amountInUSD * 86;
29 | double incentiveAmount = amountInBDT * 0.02;
30 | this.balance += amountInBDT + incentiveAmount;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/isp/violation/account/SavingsAccount.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.isp.violation.account;
2 |
3 | public interface SavingsAccount {
4 | public double getBalance();
5 |
6 | public void creditLocalAmount(double amountInBDT);
7 |
8 | public void creditInternationalAmount(double amountInUSD);
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/isp/violation/account/StudentAccount.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.isp.violation.account;
2 |
3 | import com.techtong.solid.isp.refactored.account.BaseAccount;
4 |
5 | public class StudentAccount extends BaseAccount implements SavingsAccount {
6 | private String institutionName;
7 |
8 | public StudentAccount(int accountId,
9 | String accountName,
10 | double balance,
11 | String institutionName) {
12 | super(accountId, accountName, balance);
13 | this.institutionName = institutionName;
14 | }
15 |
16 | @Override
17 | public void creditLocalAmount(double amountInBDT) {
18 | this.balance += amountInBDT;
19 | }
20 |
21 | @Override
22 | public void creditInternationalAmount(double amountInUSD) {
23 | throw new UnsupportedOperationException("International amount transfer is not applicable for student account");
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/refactored/Main.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.refactored;
2 |
3 |
4 | import com.techtong.solid.lsp.refactored.model.*;
5 |
6 | import java.util.ArrayList;
7 | import java.util.List;
8 | import java.util.logging.Level;
9 | import java.util.logging.Logger;
10 |
11 | public class Main {
12 | private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME) ;
13 |
14 | public static void main(String[] args){
15 | List employees = List.of(
16 | new PermanentEmployee(1, "Sabbir"),
17 | new TemporaryEmployee(2, "Sazzad"));
18 |
19 | for( EmployeeBonusEligible employee : employees ){
20 | System.out.println(employee.toString() + " Employee Bonus : " + employee.calculateBonus(1000));
21 | }
22 |
23 | System.out.println("----------");
24 | List employeesOnly = List.of(
25 | new PermanentEmployee(1, "Sabbir"),
26 | new TemporaryEmployee(2, "Sazzad"),
27 | new ContractEmployee(3, "Abcdef")
28 | );
29 |
30 | for( IEmployee employee : employeesOnly ){
31 | System.out.println(employee.toString() + " Employee is eligible for Insurance : " + employee.isEligibleForInsurance());
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/refactored/model/ContractEmployee.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.refactored.model;
2 |
3 | public class ContractEmployee extends Employee {
4 |
5 | public ContractEmployee(int id, String name) {
6 | super(id,name);
7 | }
8 |
9 | public boolean isEligibleForInsurance() {
10 | return false;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/refactored/model/Employee.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.refactored.model;
2 |
3 | public abstract class Employee implements IEmployee {
4 | private final int id;
5 | private final String name;
6 |
7 | public int getId() {
8 | return id;
9 | }
10 | public String getName() {
11 | return name;
12 | }
13 |
14 | public Employee(int id, String name){
15 | this.id = id;
16 | this.name = name;
17 | }
18 | @Override
19 | public String toString() {
20 | return "Employee ID: " + this.getId() + " Employee Name : " + this.getName();
21 | }
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/refactored/model/EmployeeBonusEligible.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.refactored.model;
2 |
3 | public interface EmployeeBonusEligible {
4 | double calculateBonus(double salary);
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/refactored/model/IEmployee.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.refactored.model;
2 |
3 | public interface IEmployee {
4 | boolean isEligibleForInsurance();
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/refactored/model/PermanentEmployee.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.refactored.model;
2 |
3 |
4 | public class PermanentEmployee extends Employee implements EmployeeBonusEligible {
5 |
6 | public PermanentEmployee(int id, String name) {
7 | super(id, name);
8 | }
9 |
10 | @Override
11 | public double calculateBonus(double salary) {
12 | return salary * .1;
13 | }
14 |
15 | @Override
16 | public boolean isEligibleForInsurance() {
17 | return true;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/refactored/model/TemporaryEmployee.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.refactored.model;
2 |
3 | public class TemporaryEmployee extends Employee implements EmployeeBonusEligible{
4 |
5 | public TemporaryEmployee(int id, String name) {
6 | super(id, name);
7 | }
8 |
9 | @Override
10 | public double calculateBonus(double salary) {
11 | return salary * .05;
12 | }
13 |
14 | public boolean isEligibleForInsurance() {
15 | return false;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/violation/Main.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.violation;
2 |
3 | import com.techtong.solid.lsp.violation.model.ContractEmployee;
4 | import com.techtong.solid.lsp.violation.model.Employee;
5 | import com.techtong.solid.lsp.violation.model.PermanentEmployee;
6 | import com.techtong.solid.lsp.violation.model.TemporaryEmployee;
7 |
8 | import java.util.ArrayList;
9 | import java.util.List;
10 | import java.util.logging.Level;
11 | import java.util.logging.Logger;
12 |
13 | public class Main {
14 | private final static Logger LOGGER = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME) ;
15 |
16 | public static void main(String[] args){
17 | List employees = new ArrayList<>();
18 | employees.add( new PermanentEmployee(1, "Sabbir"));
19 | employees.add( new TemporaryEmployee(2, "Sazzad"));
20 | employees.add( new ContractEmployee(3, "Abc"));
21 |
22 | for( Employee employee : employees ) {
23 |
24 | System.out.println("Employee ID: " + employee.getId() + " Employee Name : " + employee.getName() + " - Employee is eligible for Insurance : " + employee.isEligibleForInsurance());
25 | }
26 |
27 | System.out.println("--------------------");
28 |
29 | for( Employee employee : employees ){
30 | try {
31 | System.out.println("Employee ID: " + employee.getId() + " Employee Name : " + employee.getName() + " Employee Bonus : " + employee.calculateBonus(1000));
32 | }catch (UnsupportedOperationException exception) {
33 | LOGGER.log(Level.SEVERE, " This employee is not eligible for bonus");
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/violation/model/ContractEmployee.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.violation.model;
2 |
3 | public class ContractEmployee extends Employee{
4 |
5 | public ContractEmployee(int id, String name) {
6 | super(id, name);
7 | }
8 |
9 | @Override
10 | public boolean isEligibleForInsurance() {
11 | return false;
12 | }
13 |
14 | @Override
15 | public double calculateBonus(float salary) {
16 | throw new UnsupportedOperationException("Not implemented");
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/violation/model/Employee.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.violation.model;
2 |
3 | public abstract class Employee {
4 | private final int id;
5 | private final String name;
6 |
7 | public int getId() {
8 | return id;
9 | }
10 |
11 | public String getName() {
12 | return name;
13 | }
14 |
15 | public Employee(int id, String name){
16 | this.id = id;
17 | this.name = name;
18 | }
19 | public abstract double calculateBonus(float salary);
20 | public abstract boolean isEligibleForInsurance();
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/violation/model/PermanentEmployee.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.violation.model;
2 |
3 | public class PermanentEmployee extends Employee{
4 |
5 | public PermanentEmployee(int id, String name) {
6 | super(id, name);
7 | }
8 |
9 | @Override
10 | public boolean isEligibleForInsurance() {
11 | return true;
12 | }
13 |
14 | @Override
15 | public double calculateBonus(float salary) {
16 | return salary * .1;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/lsp/violation/model/TemporaryEmployee.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.lsp.violation.model;
2 |
3 | public class TemporaryEmployee extends Employee{
4 |
5 | public TemporaryEmployee(int id, String name) {
6 | super(id, name);
7 | }
8 |
9 | @Override
10 | public boolean isEligibleForInsurance() {
11 | return false;
12 | }
13 |
14 | @Override
15 | public double calculateBonus(float salary) {
16 | return salary * .05;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/OCP.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp;
2 |
3 | import com.techtong.solid.ocp.violation.models.FoodItem;
4 | import com.techtong.solid.ocp.violation.models.FriedFood;
5 | import com.techtong.solid.ocp.violation.models.GrilledFood;
6 | import com.techtong.solid.ocp.violation.BadKitchenService;
7 |
8 | import java.util.List;
9 |
10 | public class OCP {
11 | public static void main(String[] args) {
12 |
13 | List foodItems = List.of(
14 | new GrilledFood("steak"),
15 | new FriedFood("chicken")
16 | );
17 |
18 | BadKitchenService kitchenService = new BadKitchenService();
19 |
20 | System.out.println("Preparing Items:");
21 | kitchenService.prepareItems(foodItems);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/refactored/DecentKitchenService.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp.refactored;
2 |
3 | import com.techtong.solid.ocp.refactored.models.FoodItem;
4 |
5 | import java.util.List;
6 |
7 | public class DecentKitchenService {
8 | public void prepareItems(List foodItems) {
9 | foodItems.forEach(FoodPreparer::prepare);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/refactored/FoodPreparer.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp.refactored;
2 |
3 | public interface FoodPreparer {
4 | public void prepare();
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/refactored/models/BakedFood.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp.refactored.models;
2 |
3 | import com.techtong.solid.ocp.refactored.FoodPreparer;
4 |
5 | public class BakedFood extends FoodItem implements FoodPreparer {
6 | public BakedFood(String name) {
7 | super(name);
8 | }
9 |
10 | @Override
11 | public void prepare() {
12 | System.out.println("---> Baking " + this.getName()); // some grilling logic
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/refactored/models/FoodItem.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp.refactored.models;
2 |
3 | import com.techtong.solid.ocp.refactored.FoodPreparer;
4 |
5 | public abstract class FoodItem implements FoodPreparer {
6 | private String name;
7 |
8 | public FoodItem(String name) {
9 | this.name = name;
10 | }
11 |
12 | public String getName() {
13 | return name;
14 | }
15 |
16 | public void setName(String name) {
17 | this.name = name;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/refactored/models/FriedFood.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp.refactored.models;
2 |
3 | public class FriedFood extends FoodItem {
4 | public FriedFood(String name) {
5 | super(name);
6 | }
7 |
8 | @Override
9 | public void prepare() {
10 | System.out.println("====> Frying " + this.getName());
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/refactored/models/GrilledFood.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp.refactored.models;
2 |
3 | public class GrilledFood extends FoodItem {
4 | public GrilledFood(String name) {
5 | super(name);
6 | }
7 |
8 | @Override
9 | public void prepare() {
10 | System.out.println("====> Grilling " + this.getName());
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/refactored/models/SauteedFood.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp.refactored.models;
2 |
3 | import com.techtong.solid.ocp.refactored.FoodPreparer;
4 | import com.techtong.solid.ocp.violation.models.FoodItem;
5 |
6 | public class SauteedFood extends FoodItem implements FoodPreparer {
7 | public SauteedFood(String name) {
8 | super(name);
9 | }
10 |
11 | @Override
12 | public void prepare() {
13 | System.out.println("---> Sauteeing " + this.getName()); // some grilling logic
14 | }
15 | }
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/violation/BadKitchenService.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp.violation;
2 |
3 | import com.techtong.solid.ocp.violation.models.FoodItem;
4 | import com.techtong.solid.ocp.violation.models.FriedFood;
5 | import com.techtong.solid.ocp.violation.models.GrilledFood;
6 |
7 | import java.util.List;
8 |
9 | public class BadKitchenService {
10 | public void prepareItems(List foodItems) {
11 | for (final FoodItem foodItem : foodItems) {
12 | if (foodItem instanceof GrilledFood) {
13 | System.out.println("---> Grilling " + foodItem.getName());
14 | }
15 |
16 | if (foodItem instanceof FriedFood) {
17 | System.out.println("---> Frying " + foodItem.getName());
18 | }
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/violation/models/FoodItem.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp.violation.models;
2 |
3 | public abstract class FoodItem {
4 | private String name;
5 |
6 | public FoodItem(String name) {
7 | this.name = name;
8 | }
9 |
10 | public String getName() {
11 | return name;
12 | }
13 |
14 | public void setName(String name) {
15 | this.name = name;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/violation/models/FriedFood.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp.violation.models;
2 |
3 | public class FriedFood extends FoodItem {
4 | public FriedFood(String name) {
5 | super(name);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/ocp/violation/models/GrilledFood.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.ocp.violation.models;
2 |
3 | public class GrilledFood extends FoodItem {
4 | public GrilledFood(String name) {
5 | super(name);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/srp/refactored/Customer.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.srp.refactored;
2 |
3 | public class Customer {
4 | private final String name;
5 | private final int age;
6 |
7 | public Customer(String name, int age) {
8 | this.name = name;
9 | this.age = age;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/srp/refactored/Item.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.srp.refactored;
2 |
3 | public class Item {
4 | private String name;
5 | private Double price;
6 |
7 | public Item(String name, Double price) {
8 | this.name = name;
9 | this.price = price;
10 | }
11 |
12 | public String getName() {
13 | return name;
14 | }
15 |
16 | public void setName(String name) {
17 | this.name = name;
18 | }
19 |
20 | public Double getPrice() {
21 | return price;
22 | }
23 |
24 | public void setPrice(Double price) {
25 | this.price = price;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/srp/refactored/Main.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.srp.refactored;
2 |
3 | import com.techtong.solid.srp.refactored.pricecalculation.ItemPriceCalculationService;
4 |
5 | import java.util.List;
6 |
7 | public class Main {
8 |
9 | public static void main(String[] args) {
10 | Item cleanCodeBook = new Item("Clean Code", 100.0);
11 | Item mask = new Item("Mask", 10.0);
12 | Item tShirt = new Item("Mask", 20.0);
13 |
14 | int plasticBagTaken = 2;
15 | int tax = 10;
16 |
17 | List- itemsPurchased = List.of(cleanCodeBook, mask, tShirt);
18 |
19 | ItemPriceCalculationService itemPriceCalculation = new ItemPriceCalculationService();
20 |
21 | double totalPriceOfItems = itemPriceCalculation.calculateItemPrice(itemsPurchased,
22 | plasticBagTaken,
23 | tax);
24 |
25 | System.out.println("Total Prices of items purchased : " + totalPriceOfItems);
26 |
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/srp/refactored/logger/ConsoleLogger.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.srp.refactored.logger;
2 |
3 | public class ConsoleLogger {
4 | public void logInConsole(String message) {
5 | System.out.println("Console Log : " + message);
6 | }
7 | }
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/srp/refactored/logger/FileLogger.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.srp.refactored.logger;
2 |
3 | public class FileLogger {
4 | public void logInFile(String message) {
5 | System.out.println("File Log: " + message);
6 | }
7 | }
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/srp/refactored/logger/Logger.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.srp.refactored.logger;
2 |
3 | public class Logger {
4 |
5 | private static final FileLogger fileLogger = new FileLogger();
6 | private static final ConsoleLogger consoleLogger = new ConsoleLogger();
7 |
8 | public static void info(String message) {
9 | fileLogger.logInFile(message);
10 | consoleLogger.logInConsole(message);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/srp/refactored/pricecalculation/ItemPriceCalculationService.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.srp.refactored.pricecalculation;
2 |
3 | import com.techtong.solid.srp.refactored.Item;
4 | import com.techtong.solid.srp.refactored.logger.Logger;
5 |
6 | import java.util.List;
7 |
8 | public class ItemPriceCalculationService {
9 | private double plasticBagPrice = 2.0;
10 | private final TaxCalculationService taxCalculationService = new TaxCalculationService();
11 |
12 | public double calculateItemPrice(List
- items,
13 | int numberOfPlasticBags,
14 | int tax) {
15 | double itemPrices = getTotalItemPrices(items);
16 | calculatePlasticBagPrice(items.size());
17 |
18 | double totalTax = taxCalculationService.calculateTax(itemPrices, tax);
19 |
20 | double totalPrice = itemPrices + totalTax + numberOfPlasticBags * plasticBagPrice;
21 | Logger.info("Total Price of the items -> " + totalPrice);
22 | return totalPrice;
23 | }
24 |
25 | public double getTotalItemPrices(List
- items) {
26 | return items
27 | .stream()
28 | .mapToDouble(Item::getPrice)
29 | .sum();
30 | }
31 |
32 | public void calculatePlasticBagPrice(int totalItems) {
33 | if (totalItems > 2) {
34 | plasticBagPrice = plasticBagPrice * 0.5;
35 | Logger.info("More than 2 items purchased. Reducing plastic bag price");
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/srp/refactored/pricecalculation/TaxCalculationService.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.srp.refactored.pricecalculation;
2 |
3 | import com.techtong.solid.srp.refactored.logger.Logger;
4 |
5 | public class TaxCalculationService {
6 |
7 | public double calculateTax(double itemPrice, double tax) {
8 | if (itemPrice <= 100) {
9 | Logger.info("Item price is more than 100. 80 Percent of the actual tax applicable");
10 | tax = tax * .80;
11 | } else if (itemPrice >= 100 && itemPrice <= 150) {
12 | Logger.info("Item price is more than 100 but less than 150. 90 Percent of the actual tax applicable");
13 | tax = tax * .90;
14 | }
15 | return tax;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/srp/violation/Customer.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.srp.violation;
2 |
3 | import java.util.List;
4 |
5 | public class Customer {
6 | private final String name;
7 | private final int age;
8 | private final List
- items;
9 | private final int numberOfPlasticBags;
10 | private double plasticBagPrice = 2.00;
11 |
12 | public Customer(String name, int age, List
- items, int numberOfPlasticBags) {
13 | this.name = name;
14 | this.age = age;
15 | this.items = items;
16 | this.numberOfPlasticBags = numberOfPlasticBags;
17 | }
18 |
19 | public double calculatePrice(double tax) {
20 | int totalItems = items.size();
21 | double itemPrice = items
22 | .stream()
23 | .mapToDouble(Item::getPrice)
24 | .sum();
25 |
26 | if (totalItems > 2) {
27 | plasticBagPrice = plasticBagPrice * 0.5;
28 | logInformation("More than 2 items purchased. Reducing plastic bag price");
29 | }
30 |
31 | if (itemPrice <= 100) {
32 | logInformation("Item price is more than 100. 80 Percent of the actual tax applicable");
33 | tax = tax * .80;
34 | } else if (itemPrice >= 100 && itemPrice <= 150) {
35 | logInformation("Item price is more than 100 but less than 150. 90 Percent of the actual tax applicable");
36 | tax = tax * .90;
37 | }
38 | double totalPrice = itemPrice + tax + this.numberOfPlasticBags * plasticBagPrice;
39 | logInformation("Total Price of the items -> " + totalPrice);
40 | return totalPrice;
41 | }
42 |
43 | public void logInformation(String message) {
44 | FileLogger fileLogger = new FileLogger();
45 | ConsoleLogger consoleLogger = new ConsoleLogger();
46 |
47 | fileLogger.logInFile(message);
48 | consoleLogger.logInConsole(message);
49 | }
50 |
51 | public class FileLogger {
52 | public void logInFile(String message) {
53 | System.out.println("File Log: " + message);
54 | }
55 | }
56 |
57 | public class ConsoleLogger {
58 | public void logInConsole(String message) {
59 | System.out.println("Console Log : " + message);
60 | }
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/srp/violation/Item.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.srp.violation;
2 |
3 | public class Item {
4 | private String name;
5 | private Double price;
6 |
7 | public Item(String name, Double price) {
8 | this.name = name;
9 | this.price = price;
10 | }
11 |
12 | public String getName() {
13 | return name;
14 | }
15 |
16 | public void setName(String name) {
17 | this.name = name;
18 | }
19 |
20 | public Double getPrice() {
21 | return price;
22 | }
23 |
24 | public void setPrice(Double price) {
25 | this.price = price;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/techtong/solid/srp/violation/Main.java:
--------------------------------------------------------------------------------
1 | package com.techtong.solid.srp.violation;
2 |
3 | import java.util.List;
4 |
5 | public class Main {
6 |
7 | public static void main(String[] args) {
8 | Item cleanCodeBook = new Item("Clean Code", 100.0);
9 | Item mask = new Item("Mask", 10.0);
10 | Item tShirt = new Item("Mask", 20.0);
11 |
12 | int plasticBagTaken = 2;
13 | int tax = 10;
14 |
15 | var itemsPurchased = List.of(cleanCodeBook, mask, tShirt);
16 |
17 | Customer uncleBob = new Customer("Robert C Martin",
18 | 68,
19 | itemsPurchased,
20 | plasticBagTaken);
21 |
22 | double totalPriceOfItems = uncleBob.calculatePrice(tax);
23 |
24 | System.out.println("Total Prices of items purchased : " + totalPriceOfItems);
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------