├── DesignPatterns
├── .gitignore
├── README.md
├── pom.xml
└── src
│ └── com
│ └── tirthal
│ └── learning
│ └── design
│ └── patterns
│ ├── behavioral
│ ├── README.md
│ ├── observer
│ │ ├── AppTestDrive.java
│ │ ├── Auctioner.java
│ │ ├── Bidder.java
│ │ ├── DisplayElement.java
│ │ ├── Observer.java
│ │ ├── README.md
│ │ └── Subject.java
│ └── strategy
│ │ ├── AppTestDrive.java
│ │ ├── MakeMyTrip.java
│ │ ├── Merchant.java
│ │ ├── Myntra.java
│ │ ├── PayByCash.java
│ │ ├── PayByCreditCard.java
│ │ ├── PayByPaypal.java
│ │ ├── PaymentStrategy.java
│ │ └── README.md
│ ├── creational
│ ├── README.md
│ ├── abstractfactory
│ │ ├── AmexFactory.java
│ │ ├── AmexGoldCreditCard.java
│ │ ├── AmexGoldValidator.java
│ │ ├── AmexPlatinumCreditCard.java
│ │ ├── AmexPlatinumValidator.java
│ │ ├── AppTestDrive.java
│ │ ├── CardType.java
│ │ ├── CreditCard.java
│ │ ├── CreditCardFactory.java
│ │ ├── MasterCardFactory.java
│ │ ├── MasterEliteCreditCard.java
│ │ ├── MasterEliteValidator.java
│ │ ├── MasterGoldCreditCard.java
│ │ ├── MasterGoldValidator.java
│ │ ├── README.md
│ │ ├── Validator.java
│ │ ├── VisaBlackCreditCard.java
│ │ ├── VisaBlackValidator.java
│ │ ├── VisaFactory.java
│ │ ├── VisaGoldCreditCard.java
│ │ └── VisaGoldValidator.java
│ ├── builder
│ │ ├── AppTestDrive.java
│ │ ├── Person.java
│ │ └── README.md
│ ├── factorymethod
│ │ ├── AppTestDrive.java
│ │ ├── CashPayment.java
│ │ ├── CreditCardPayment.java
│ │ ├── NetbankingPayment.java
│ │ ├── Payment.java
│ │ ├── PaymentFactory.java
│ │ ├── PaymentOptions.java
│ │ └── README.md
│ ├── objectpool
│ │ └── README.md
│ ├── prototype
│ │ ├── AppTestDrive.java
│ │ ├── Circle.java
│ │ ├── README.md
│ │ ├── Rectangle.java
│ │ ├── Shape.java
│ │ ├── ShapeRegistry.java
│ │ └── Square.java
│ └── singleton
│ │ ├── AppTestDrive.java
│ │ ├── LoggerUsingEagerInstantiation.java
│ │ ├── LoggerUsingEnum.java
│ │ ├── LoggerUsingInnerClass.java
│ │ ├── LoggerUsingLazyInstantiationDoubleLocking.java
│ │ └── README.md
│ └── structural
│ ├── README.md
│ ├── adapter
│ ├── AppTestDrive.java
│ ├── CsvAdapterImpl.java
│ ├── CsvFormattable.java
│ ├── CsvFormatter.java
│ ├── NewlineFormatter.java
│ ├── README.md
│ └── TextFormattable.java
│ ├── bridge
│ ├── AppTestDrive.java
│ ├── Assemble.java
│ ├── Bike.java
│ ├── Car.java
│ ├── Produce.java
│ ├── README.md
│ ├── Vehicle.java
│ └── Workshop.java
│ ├── composite
│ ├── AppTestDrive.java
│ ├── Menu.java
│ ├── MenuComponent.java
│ ├── MenuItem.java
│ └── README.md
│ └── decorator
│ ├── AppTestDrive.java
│ ├── Beverage.java
│ ├── CondimentDecorator.java
│ ├── Milk.java
│ ├── README.md
│ ├── RedTea.java
│ ├── Sugar.java
│ └── TeaMasala.java
├── DesignPrinciples
├── .gitignore
├── README.md
├── pom.xml
└── src
│ └── com
│ └── tirthal
│ └── learning
│ └── oop
│ ├── README.md
│ ├── concepts
│ ├── AggregationComposition_TestDrive.java
│ ├── Cohesion_TestDrive.java
│ ├── Delegation_InsteadOfGetterSetter_TestDrive.java
│ ├── Delegation_TestDrive.java
│ ├── Encapsulation_TestDrive.java
│ ├── Inheritance_TestDrive.java
│ ├── LooseCoupling_TestDrive.java
│ ├── Polymorphism_TestDrive.java
│ └── README.md
│ └── design
│ └── principles
│ └── clazz
│ └── solid
│ ├── README.md
│ ├── dip
│ ├── README.md
│ └── authentication
│ │ ├── bad
│ │ ├── LoginManager.java
│ │ ├── SimpleAuthenticator.java
│ │ └── User.java
│ │ └── good
│ │ ├── Authenticator.java
│ │ ├── LDAPAuthenticator.java
│ │ ├── LoginManager.java
│ │ ├── SimpleAuthenticator.java
│ │ └── User.java
│ ├── isp
│ ├── README.md
│ └── order
│ │ ├── bad
│ │ ├── Order.java
│ │ └── OrderService.java
│ │ └── good
│ │ ├── Order.java
│ │ ├── OrderProcessingService.java
│ │ └── OrderService.java
│ ├── lsp
│ ├── README.md
│ └── mediaplayer
│ │ ├── bad
│ │ ├── ClientTestProgram.java
│ │ ├── DivMediaPlayer.java
│ │ ├── MediaPlayer.java
│ │ ├── VideoUnsupportedException.java
│ │ ├── VlcMediaPlayer.java
│ │ └── WinampMediaPlayer.java
│ │ └── good
│ │ ├── AudioMediaPlayer.java
│ │ ├── ClientTestProgram.java
│ │ ├── DivMediaPlayer.java
│ │ ├── MediaPlayer.java
│ │ ├── VideoMediaPlayer.java
│ │ ├── VideoUnsupportedException.java
│ │ ├── VlcMediaPlayer.java
│ │ └── WinampMediaPlayer.java
│ ├── ocp
│ ├── README.md
│ ├── drawing
│ │ ├── bad
│ │ │ ├── Circle.java
│ │ │ ├── GraphicEditor.java
│ │ │ ├── GraphicEditorTestDrive.java
│ │ │ ├── Rectangle.java
│ │ │ └── Shape.java
│ │ └── good
│ │ │ ├── Circle.java
│ │ │ ├── GraphicEditor.java
│ │ │ ├── GraphicEditorTestDrive.java
│ │ │ ├── Rectangle.java
│ │ │ └── Shape.java
│ ├── exporter
│ │ ├── bad
│ │ │ └── Order.java
│ │ └── good
│ │ │ ├── JsonExporter.java
│ │ │ ├── JsonImporter.java
│ │ │ ├── Order.java
│ │ │ ├── XmlExporter.java
│ │ │ └── XmlImporter.java
│ └── parsing
│ │ ├── bad
│ │ └── FileParser.java
│ │ └── good
│ │ └── FileParser.java
│ └── srp
│ ├── README.md
│ └── modem
│ ├── bad
│ ├── IModem.java
│ ├── ModemFast.java
│ ├── ModemFastClient.java
│ ├── ModemSlow.java
│ └── ModemSlowClient.java
│ └── good
│ ├── ConnectionManager.java
│ ├── DataChannelFastMode.java
│ ├── DataChannelSlowMode.java
│ ├── IConnection.java
│ ├── IDataChannel.java
│ ├── Modem.java
│ ├── ModemFastClient.java
│ └── ModemSlowClient.java
├── LICENSE
└── README.md
/DesignPatterns/.gitignore:
--------------------------------------------------------------------------------
1 | /.settings/
2 | /target/
3 | /.classpath
4 | /.project
5 |
--------------------------------------------------------------------------------
/DesignPatterns/README.md:
--------------------------------------------------------------------------------
1 | # Learn Design Patterns
2 |
3 | This project contains sample java code (by practical examples along with easy to understand comments) to learn design patterns.
4 |
5 | ## How to use this project?
6 |
7 | Just import this project in Eclipse as an "Existing Maven Project". If require, do necessary configuration to fix build path errors (e.g. setup JRE 1.8).
8 |
9 | ## Motive
10 |
11 | Lastly in year 2005, I read "Head First Design Patterns" book and then I consider patterns usage in coding as and when required.
12 |
13 | Again I thought to revise my design patterns knowledge in chunks by 2016 year, and this project would be consequence of it.
14 |
15 | I consider to take some content from below resources for the quick reference, so credit goes to authors of "Tutorials Point", "Java Point", "SourceMaking Site", "OODesign Site", "Design Patterns DZone Refcard" and "Design Patterns in Java courses of Pluralsight".
16 |
17 | * http://www.javatpoint.com/design-patterns-in-java
18 | * http://www.tutorialspoint.com/design_pattern/index.htm
19 | * http://sourcemaking.com/design_patterns
20 | * http://www.oodesign.com/
21 | * http://refcardz.dzone.com/refcardz/design-patterns
22 | * https://app.pluralsight.com/library/search?q=%22Design+Patterns+in+Java%22
23 |
24 | Additionally, I intend to implement some of java code examples based on my experience.
25 |
26 |
27 | ## Design Patterns
28 |
29 | * are recurring solutions to software design problems you find again and again in real-world application development.
30 | * are just a description or template for how to solve a problem that can be used in many different situations, so can't be transformed directly into code.
31 | * can speed up the development process by providing tested, proven development paradigms.
32 | * allow developers to communicate using well-known, well understood names for software interactions.
33 | * allow you to get experience reuse, instead of code reuse.
34 |
35 | Patterns can be categorized under the following heads based on Scope.
36 |
37 | * Class - Deals with class relationships that can be changed at compile time.
38 | * Object - Deals with object relationships that can be changed at runtime.
39 |
40 | The design patterns in java are generally categorized as following.
41 |
42 | ## Creational Patterns
43 |
44 | Focuses on object instantiation or how objects are created. Let you construct objects such that they can be decoupled from their implementing system. [Start exploring creation patterns](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/creational),
45 |
46 | * [Singleton](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/singleton)
47 | * [Builder](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/builder)
48 | * [Prototype](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/prototype)
49 | * [Factory Method](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/factorymethod)
50 | * [Abstract Factory](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory)
51 | * [Object Pool](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/objectpool)
52 |
53 | ## Structural Patterns
54 |
55 | Focuses on the relationship of classes structure. Let you ease the design by identifying a simple way to realize relationships between entities. [Start exploring structural patterns](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/structural),
56 |
57 | * [Adapter](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/adapter)
58 | * [Bridge](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/bridge)
59 | * [Composite](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/composite)
60 | * [Decorator](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/decorator)
61 | * Facade
62 | * Flyweight
63 | * Proxy
64 | * Private Class Data
65 |
66 | ## Behavioral Patterns
67 |
68 | Focuses on the communication between objects. Let you manage algorithms, relationships, and responsibilities between objects. [Start exploring behavioral patterns](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral),
69 |
70 | * Chain of Responsibility
71 | * Command
72 | * Interpreter
73 | * Iterator
74 | * Mediator
75 | * Memento
76 | * Null Object
77 | * [Observer](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/observer)
78 | * State
79 | * [Strategy](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy)
80 | * Template Method
81 | * Visitor
82 |
83 | ## Concurrency Patterns
84 |
85 | Let you deal with the multi-threaded programming paradigm.
86 |
87 | To be added in future
88 |
89 |
90 |
91 | ## Disclaimer
92 |
93 | The code snippet are mainly targeted for learning purpose, and not focused for producing production code quality.
--------------------------------------------------------------------------------
/DesignPatterns/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 | DesignPatterns
6 | DesignPatterns
7 | jar
8 | 0.0.1-SNAPSHOT
9 | Sample code snippet to learn design patterns
10 |
11 |
12 | src
13 |
14 |
15 | org.apache.maven.plugins
16 | maven-compiler-plugin
17 | 2.3.2
18 |
19 | 1.8
20 | 1.8
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/README.md:
--------------------------------------------------------------------------------
1 | # Behavioral Patterns
2 |
3 | * The behavioral patterns provide solution for the better interaction between objects and how to provide lose coupling and flexibility to extend easily.
4 | * The behavioral patterns are about communication between separate objects and they specify how separate objects interact.
5 | * The behavioral patterns describe the ways objects and classes interact and divide responsibilities among themselves.
6 |
7 | ## See it in Action:
8 |
9 | * Chain of Responsibility - A way of passing a request between a chain of objects
10 | * Command - Encapsulate a command request as an object
11 | * Interpreter - A way to include language elements in a program
12 | * Iterator - Sequentially access the elements of a collection
13 | * Mediator - Defines simplified communication between classes
14 | * Memento - Capture and restore an object's internal state
15 | * Null Object - Designed to act as a default value of an object
16 | * [Observer](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/observer) - A way of notifying change to a number of classes
17 | * State - Alter an object's behavior when its state changes
18 | * [Strategy](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy) - Encapsulates an algorithm inside a class
19 | * Template Method - Defer the exact steps of an algorithm to a subclass
20 | * Visitor - Defines a new operation to a class without change
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/observer/AppTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.observer;
2 |
3 | import java.util.InputMismatchException;
4 | import java.util.Scanner;
5 |
6 | /**
7 | * Demo client which registers and unregister bidders (observers) with auctioner (subject) participate in the auction. If we see, client app is not
8 | * responsible to broadcast updates to all registered observers, rather it is accomplished through observer pattern.
9 | *
10 | * See implementation classes of Subject and Observer interfaces.
11 | *
12 | * @author tirthalp
13 | *
14 | */
15 | public class AppTestDrive {
16 |
17 | public static void main(String[] args) {
18 | Auctioner auctioner = new Auctioner();
19 |
20 | Bidder b1 = new Bidder("Bidder One - Kat");
21 | Bidder b2 = new Bidder("Bidder Two - Ash");
22 | Bidder b3 = new Bidder("Bidder Three - Jade");
23 |
24 | // Register bidders
25 | System.out.println("------ Registering all bidders");
26 | auctioner.registerObserver(b1);
27 | auctioner.registerObserver(b2);
28 | auctioner.registerObserver(b3);
29 |
30 | // Auctioner to broadcast bid price
31 | System.out.println("------ Enter 'C' to close the bid.");
32 | Scanner scan = new Scanner(System.in);
33 | boolean isBidClosed = false;
34 | do {
35 | if (auctioner.getBidPrice() <= 0)
36 | System.out.print("Enter a starting bid price: ");
37 | else
38 | System.out.print("Enter a new highest bid price: ");
39 |
40 | try {
41 | auctioner.setBidPrice(scan.nextInt());
42 | } catch (InputMismatchException e) {
43 | System.out.println("------ This bid is CLOSED now.");
44 | isBidClosed = true;
45 | scan.close();
46 | }
47 | } while (isBidClosed == false);
48 |
49 | // Unregister bidders
50 | System.out.println("------ Unregistering all bidders");
51 | auctioner.removeObserver(b1);
52 | auctioner.removeObserver(b2);
53 | auctioner.removeObserver(b3);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/observer/Auctioner.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.observer;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * Auctioner is implementation of Subject, and offers functionality to register observers, notify state updates to registered observers and unregister
8 | * observers.
9 | *
10 | * @author tirthalp
11 | *
12 | */
13 | public class Auctioner implements Subject {
14 | private List observers;
15 | private float bidPrice;
16 |
17 | public Auctioner() {
18 | observers = new ArrayList();
19 | }
20 |
21 | // Register
22 | @Override
23 | public void registerObserver(Observer o) {
24 | observers.add(o);
25 | System.out.println("Registered: " + o.toString());
26 | }
27 |
28 | // Unregister
29 | @Override
30 | public void removeObserver(Observer o) {
31 | int i = observers.indexOf(o);
32 | if (i >= 0) {
33 | observers.remove(i);
34 | }
35 | System.out.println("Unregistered: " + o.toString());
36 | }
37 |
38 | // Notify state changes
39 | @Override
40 | public void notifyObservers() {
41 | for (int i = 0; i < observers.size(); i++) {
42 | Observer observer = observers.get(i);
43 | observer.update(bidPrice);
44 | }
45 | }
46 |
47 | private void bidPriceChanged() {
48 | notifyObservers();
49 | }
50 |
51 | public void setBidPrice(float bidPrice) {
52 | this.bidPrice = bidPrice;
53 | bidPriceChanged();
54 | }
55 |
56 | public float getBidPrice() {
57 | return bidPrice;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/observer/Bidder.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.observer;
2 |
3 | /**
4 | * Bidder implementation of Observer type
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Bidder implements Observer, DisplayElement {
10 |
11 | private String name;
12 |
13 | public Bidder(String name) {
14 | this.name = name;
15 | }
16 |
17 | @Override
18 | public void update(float price) {
19 | // Bidder to propose new bid price in the auction
20 | float newPriceForBidding = Math.round(price + (Math.random() * 100) + (Math.random() * 100));
21 | display(newPriceForBidding);
22 | }
23 |
24 | @Override
25 | public void display(float proposedNewBid) {
26 | System.out.println("Bid of " + this.toString() + " - " + proposedNewBid);
27 | }
28 |
29 | @Override
30 | public String toString() {
31 | return name;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/observer/DisplayElement.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.observer;
2 |
3 | public interface DisplayElement {
4 | public void display(float proposedNewBid);
5 | }
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/observer/Observer.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.observer;
2 |
3 | /**
4 | * Observer interface
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public interface Observer {
10 | public void update(float price);
11 | }
12 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/observer/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/observer/README.md
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/observer/Subject.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.observer;
2 |
3 | /**
4 | * Subject interface
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public interface Subject {
10 | public void registerObserver(Observer o);
11 | public void removeObserver(Observer o);
12 | public void notifyObservers();
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy/AppTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.strategy;
2 |
3 | /**
4 | * Client app for the demo of strategy pattern implementation for Payment methods
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class AppTestDrive {
10 |
11 | public static void main(String[] args) {
12 |
13 | // Client makes use of an encapsulated family of algorithms for payment
14 |
15 | // OO principle - programming to an interface, not an implementation
16 | Merchant m = new MakeMyTrip();
17 | m.pay(50); // By default it pays by cash
18 | m.setPaymentMode(new PayByPaypal()); // Change payment mode to Paypal
19 | m.pay(100);
20 |
21 | m = new Myntra();
22 | m.setPaymentMode(new PayByCreditCard());
23 | m.pay(1000);
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy/MakeMyTrip.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.strategy;
2 |
3 | public class MakeMyTrip extends Merchant {
4 |
5 | @Override
6 | protected void printMessage() {
7 | System.out.println("Your payment is successful. Thank you for booking tickets with MakeMyTrip.com and hope to see you again!!!");
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy/Merchant.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.strategy;
2 |
3 | /**
4 | * The Merchant client make use of use of an encapsulated family of algorithms for payment using PaymentStrategy interface
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public abstract class Merchant {
10 |
11 | private PaymentStrategy paymentMode;
12 |
13 | // By default make payment mode by cash
14 | public Merchant() {
15 | paymentMode = new PayByCash();
16 | }
17 |
18 | // Allow to set behavior dynamically
19 | public void setPaymentMode(PaymentStrategy paymentMode) {
20 | this.paymentMode = paymentMode;
21 | }
22 |
23 | // Delegate to the behavior class
24 | public void pay(int amount) {
25 | paymentMode.pay(amount);
26 | printMessage();
27 | System.out.println("---");
28 | }
29 |
30 | // Each merchant can display different message
31 | protected abstract void printMessage();
32 | }
33 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy/Myntra.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.strategy;
2 |
3 | public class Myntra extends Merchant {
4 |
5 | @Override
6 | protected void printMessage() {
7 | System.out.println("Your payment is successful. Thank you for shopping with Myntra.com and hope to see you again!!!");
8 | }
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy/PayByCash.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.strategy;
2 |
3 | /**
4 | * A concrete implementation of payment strategy algorithm for payment by cash
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class PayByCash implements PaymentStrategy {
10 |
11 | @Override
12 | public void pay(int amount) {
13 | System.out.println("Amount paid by cash = " + amount);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy/PayByCreditCard.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.strategy;
2 |
3 | /**
4 | * A concrete implementation of payment strategy algorithm for payment by credit card
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class PayByCreditCard implements PaymentStrategy {
10 |
11 | @Override
12 | public void pay(int amount) {
13 | System.out.println("Amount paid by credit card = " + amount);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy/PayByPaypal.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.strategy;
2 |
3 | /**
4 | * A concrete implementation of payment strategy algorithm for payment by Paypal
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class PayByPaypal implements PaymentStrategy {
10 |
11 | @Override
12 | public void pay(int amount) {
13 | System.out.println("Amount paid by paypal gateway = " + amount);
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy/PaymentStrategy.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.behavioral.strategy;
2 |
3 | /**
4 | * The interface to specify the signature of an algorithm (i.e. a behavior) for the Payment Strategy
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public interface PaymentStrategy {
10 |
11 | public void pay(int amount);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPatterns/src/com/tirthal/learning/design/patterns/behavioral/strategy/README.md
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/README.md
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/AmexFactory.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class AmexFactory extends CreditCardFactory {
4 |
5 | @Override
6 | public CreditCard getCreditCard(CardType cardType) {
7 |
8 | switch (cardType) {
9 | case GOLD:
10 | return new AmexGoldCreditCard();
11 | case PLATINUM:
12 | return new AmexPlatinumCreditCard();
13 | }
14 |
15 | return null;
16 | }
17 |
18 | @Override
19 | public Validator getValidator(CardType cardType) {
20 |
21 | switch (cardType) {
22 | case GOLD:
23 | return new AmexGoldValidator();
24 | case PLATINUM:
25 | return new AmexPlatinumValidator();
26 | }
27 |
28 | return null;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/AmexGoldCreditCard.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class AmexGoldCreditCard extends CreditCard {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/AmexGoldValidator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class AmexGoldValidator implements Validator {
4 |
5 | @Override
6 | public boolean isValid(CreditCard cc) {
7 |
8 | // credit card validation logic ...
9 |
10 | return false;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/AmexPlatinumCreditCard.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class AmexPlatinumCreditCard extends CreditCard {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/AmexPlatinumValidator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class AmexPlatinumValidator implements Validator {
4 |
5 | @Override
6 | public boolean isValid(CreditCard cc) {
7 |
8 | // credit card validation logic ...
9 |
10 | return false;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/AppTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | /**
4 | * Client app accessing example abstract factory pattern implementation
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class AppTestDrive {
10 |
11 | public static void main(String[] args) {
12 |
13 | CreditCardFactory abstractFactory = CreditCardFactory.getCreditCardFactory(900);
14 |
15 | CreditCard card1 = abstractFactory.getCreditCard(CardType.PLATINUM);
16 | System.out.println(card1);
17 |
18 | System.out.println("------------------");
19 |
20 | abstractFactory = CreditCardFactory.getCreditCardFactory(450);
21 |
22 | CreditCard card2 = abstractFactory.getCreditCard(CardType.GOLD);
23 | System.out.println(card2);
24 |
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/CardType.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public enum CardType {
4 |
5 | GOLD, PLATINUM;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/CreditCard.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public abstract class CreditCard {
4 |
5 | protected int cardNumberLength;
6 |
7 | protected int cscNumber;
8 |
9 | public int getCardNumberLength() {
10 | return cardNumberLength;
11 | }
12 |
13 | public void setCardNumberLength(int cardNumberLength) {
14 | this.cardNumberLength = cardNumberLength;
15 | }
16 |
17 | public int getCscNumber() {
18 | return cscNumber;
19 | }
20 |
21 | public void setCscNumber(int cscNumber) {
22 | this.cscNumber = cscNumber;
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/CreditCardFactory.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | /**
4 | * Example of Abstract Factory
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public abstract class CreditCardFactory {
10 |
11 | public static CreditCardFactory getCreditCardFactory(int creditScore) {
12 |
13 | if(creditScore > 750) {
14 | return new AmexFactory();
15 | }
16 | else if(creditScore <= 750 && creditScore >= 500) {
17 | return new MasterCardFactory();
18 | }
19 | else {
20 | return new VisaFactory();
21 | }
22 |
23 | }
24 |
25 | public abstract CreditCard getCreditCard(CardType cardType);
26 |
27 | public abstract Validator getValidator(CardType cardType);
28 | }
29 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/MasterCardFactory.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class MasterCardFactory extends CreditCardFactory {
4 |
5 | @Override
6 | public CreditCard getCreditCard(CardType cardType) {
7 |
8 | switch (cardType) {
9 | case GOLD:
10 | return new MasterGoldCreditCard();
11 | case PLATINUM:
12 | return new MasterEliteCreditCard();
13 | }
14 |
15 | return null;
16 | }
17 |
18 | @Override
19 | public Validator getValidator(CardType cardType) {
20 |
21 | switch (cardType) {
22 | case GOLD:
23 | return new MasterGoldValidator();
24 | case PLATINUM:
25 | return new MasterEliteValidator();
26 | }
27 |
28 | return null;
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/MasterEliteCreditCard.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class MasterEliteCreditCard extends CreditCard {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/MasterEliteValidator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class MasterEliteValidator implements Validator {
4 |
5 | @Override
6 | public boolean isValid(CreditCard cc) {
7 |
8 | // credit card validation logic ...
9 |
10 | return false;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/MasterGoldCreditCard.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class MasterGoldCreditCard extends CreditCard {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/MasterGoldValidator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class MasterGoldValidator implements Validator {
4 |
5 | @Override
6 | public boolean isValid(CreditCard cc) {
7 |
8 | // credit card validation logic ...
9 |
10 | return false;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/README.md
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/Validator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public interface Validator {
4 |
5 | public boolean isValid(CreditCard cc);
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/VisaBlackCreditCard.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class VisaBlackCreditCard extends CreditCard {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/VisaBlackValidator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class VisaBlackValidator implements Validator {
4 |
5 | @Override
6 | public boolean isValid(CreditCard cc) {
7 |
8 | // credit card validation logic ...
9 |
10 | return false;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/VisaFactory.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class VisaFactory extends CreditCardFactory {
4 |
5 | @Override
6 | public CreditCard getCreditCard(CardType cardType) {
7 |
8 | switch (cardType) {
9 | case GOLD:
10 | return new VisaGoldCreditCard();
11 | case PLATINUM:
12 | return new VisaBlackCreditCard();
13 | }
14 |
15 | return null;
16 | }
17 |
18 | @Override
19 | public Validator getValidator(CardType cardType) {
20 |
21 | switch (cardType) {
22 | case GOLD:
23 | return new VisaGoldValidator();
24 | case PLATINUM:
25 | return new VisaBlackValidator();
26 | }
27 |
28 | return null;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/VisaGoldCreditCard.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class VisaGoldCreditCard extends CreditCard {
4 |
5 | }
6 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/abstractfactory/VisaGoldValidator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.abstractfactory;
2 |
3 | public class VisaGoldValidator implements Validator {
4 |
5 | @Override
6 | public boolean isValid(CreditCard cc) {
7 |
8 | // credit card validation logic ...
9 |
10 | return false;
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/builder/AppTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.builder;
2 |
3 | /**
4 | * Client app accessing different implementations of builder pattern examples
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class AppTestDrive {
10 |
11 | public static void main(String[] args) {
12 |
13 | // --- Real world example - Java StringBuilder
14 | StringBuilder sb = new StringBuilder().append("This is an example ")
15 | .append("of the builder pattern. ");
16 | sb.insert(sb.length(), "Awesome!");
17 | System.out.println(sb.toString());
18 | System.out.println("-------------");
19 |
20 | // --- Custom builder example of Person
21 | Person person = new Person.Builder().firstName("Tirthal")
22 | .lastName("Patel")
23 | .middleName("D")
24 | .salutation("Mr.")
25 | .age(30)
26 | .build();
27 |
28 | System.out.println(person.getFirstName());
29 | System.out.println(person);
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/builder/Person.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.builder;
2 |
3 | /**
4 | * Example code snippet of builder pattern implementation - nested Person.Builder
5 | *
6 | * @author tirthalp
7 | */
8 | public class Person {
9 |
10 | // Nested Person.Builder
11 |
12 | public static class Builder {
13 |
14 | private String lastName;
15 | private String firstName;
16 | private String middleName;
17 | private String salutation;
18 | private int age;
19 |
20 | // Build immutable object
21 | public Person build() {
22 | return new Person(this);
23 | }
24 |
25 | public Builder lastName(String lastName) {
26 | this.lastName = lastName;
27 | return this;
28 | }
29 |
30 | public Builder firstName(String firstName) {
31 | this.firstName = firstName;
32 | return this;
33 | }
34 |
35 | public Builder middleName(String middleName) {
36 | this.middleName = middleName;
37 | return this;
38 | }
39 |
40 | public Builder salutation(String salutation) {
41 | this.salutation = salutation;
42 | return this;
43 | }
44 |
45 | public Builder age(int age) {
46 | this.age = age;
47 | return this;
48 | }
49 | }
50 |
51 | // Person attributes, constructor and getter methods
52 |
53 | private final String lastName;
54 | private final String firstName;
55 | private final String middleName;
56 | private final String salutation;
57 | private final int age;
58 |
59 | // private constructor, because only internal builder needs to call me to provide my instance to clients
60 | private Person(Builder builder) {
61 | this.firstName = builder.firstName;
62 | this.lastName = builder.lastName;
63 | this.middleName = builder.middleName;
64 | this.salutation = builder.salutation;
65 | this.age = builder.age;
66 | }
67 |
68 | // No setters, rather having only getters
69 | public String getLastName() {
70 | return lastName;
71 | }
72 | public String getFirstName() {
73 | return firstName;
74 | }
75 | public String getMiddleName() {
76 | return middleName;
77 | }
78 | public String getSalutation() {
79 | return salutation;
80 | }
81 | public int getAge() {
82 | return age;
83 | }
84 |
85 | @Override
86 | public int hashCode() {
87 | final int prime = 31;
88 | int result = 1;
89 | result = prime * result + age;
90 | result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
91 | result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
92 | result = prime * result + ((middleName == null) ? 0 : middleName.hashCode());
93 | result = prime * result + ((salutation == null) ? 0 : salutation.hashCode());
94 | return result;
95 | }
96 |
97 | @Override
98 | public boolean equals(Object obj) {
99 | if (this == obj)
100 | return true;
101 | if (obj == null)
102 | return false;
103 | if (getClass() != obj.getClass())
104 | return false;
105 | Person other = (Person) obj;
106 | if (age != other.age)
107 | return false;
108 | if (firstName == null) {
109 | if (other.firstName != null)
110 | return false;
111 | } else if (!firstName.equals(other.firstName))
112 | return false;
113 | if (lastName == null) {
114 | if (other.lastName != null)
115 | return false;
116 | } else if (!lastName.equals(other.lastName))
117 | return false;
118 | if (middleName == null) {
119 | if (other.middleName != null)
120 | return false;
121 | } else if (!middleName.equals(other.middleName))
122 | return false;
123 | if (salutation == null) {
124 | if (other.salutation != null)
125 | return false;
126 | } else if (!salutation.equals(other.salutation))
127 | return false;
128 | return true;
129 | }
130 |
131 | @Override
132 | public String toString() {
133 | return "Person [lastName=" + lastName + ", firstName=" + firstName + ", middleName=" + middleName
134 | + ", salutation=" + salutation + ", age=" + age + "]";
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/builder/README.md:
--------------------------------------------------------------------------------
1 | # Builder Pattern
2 |
3 | To simplify complex object creation by defining a class whose purpose is to build instances of another class. The Builder produces one main product, such that there might be more than one class in the product, but there is always one main class.
4 |
5 | ## Usage / Concepts
6 |
7 | * To handles complex constructors (i.e. to find a solution to the telescoping constructor anti-pattern) or large number of parameters.
8 | * Can force immutability on object, once construction is finished.
9 | * Object creation algorithms should be decoupled from the system.
10 | * Multiple representations of creation algorithms are required.
11 | * Runtime control over steps of construction process is required.
12 | * Offers a client object to construct a complex object by specifying only its type and content, being shielded from the details related to the object's representation.
13 |
14 | ## See it in Action / Sample Code Snippet
15 |
16 | * Java StringBuilder and custom Person class - Creating immutable object using builder approach.
17 | * Run [AppTestDrive.java](https://github.com/tirthalpatel/Learning-OOPD/blob/master/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/builder/AppTestDrive.java) and refer the corresponding code flow.
18 |
19 | ## Key Design Considerations
20 |
21 | * Flexibility over telescoping constructors.
22 | * Static inner builder class - builds immutable object and negates the need for exposed setters.
23 | * Private constructor of class, which is called by internal builder to provide class instance to clients.
24 |
25 | ## Hot Spots
26 |
27 | * Builder approach essentially doubles the number of lines of code for each attribute, however, client code benefits greatly in terms of usability and readability.
28 | * Lack of IDE support - Majority Java IDE supporting code generation for constructors and setters, however, lacking similar support for builder implementation.
29 |
30 | ## Real World Examples
31 |
32 | * [java.util.Locale.Builder](https://docs.oracle.com/javase/7/docs/api/java/util/Locale.Builder.html)
33 | * [java.lang.StringBuilder](https://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html)
34 | * [java.nio.ByteBuffer#put()](https://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#put(byte))
35 | * [javax.xml.parsers.DocumentBuilder](https://docs.oracle.com/javase/7/docs/api/javax/xml/parsers/DocumentBuilder.html)
36 | * [Lombok's Builder](https://projectlombok.org/features/Builder.html)
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/factorymethod/AppTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.factorymethod;
2 |
3 | import java.util.Calendar;
4 |
5 | /**
6 | * Client app accessing example factory method pattern implementation
7 | *
8 | * @author tirthalp
9 | *
10 | */
11 | public class AppTestDrive {
12 |
13 | public static void main(String[] args) {
14 |
15 | // --- Real world example - Java Calendar
16 | Calendar cal = Calendar.getInstance();
17 | System.out.println(cal);
18 | System.out.println("-----------------------------");
19 |
20 | // --- Custom factory method example for Payment use case
21 | Payment p = PaymentFactory.getInstance();
22 | p.pay();
23 |
24 | p = PaymentFactory.getInstance(PaymentOptions.NET_BANKING);
25 | p.pay();
26 |
27 | p = PaymentFactory.getInstance(PaymentOptions.CREDIT_CARD);
28 | p.pay();
29 |
30 | p = PaymentFactory.getInstance(PaymentOptions.CASH);
31 | p.pay();
32 |
33 | // Awesome: Factory method promotes the loose-coupling by hiding object instantiation logic from client code
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/factorymethod/CashPayment.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.factorymethod;
2 |
3 | /**
4 | * Concrete implementation of Payment interface
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class CashPayment implements Payment {
10 |
11 | @Override
12 | public void pay() {
13 | System.out.println("This is cash payment");
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/factorymethod/CreditCardPayment.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.factorymethod;
2 |
3 | /**
4 | * Concrete implementation of Payment interface
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class CreditCardPayment implements Payment {
10 |
11 | @Override
12 | public void pay() {
13 | System.out.println("This is credit card payment");
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/factorymethod/NetbankingPayment.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.factorymethod;
2 |
3 | /**
4 | * Concrete implementation of Payment interface
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class NetbankingPayment implements Payment {
10 |
11 | @Override
12 | public void pay() {
13 | System.out.println("This is net banking payment");
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/factorymethod/Payment.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.factorymethod;
2 |
3 | /**
4 | * The Payment interface for objects the factory method creates
5 | *
6 | * @author tirthalp
7 | */
8 | public interface Payment {
9 |
10 | public void pay();
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/factorymethod/PaymentFactory.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.factorymethod;
2 |
3 | /**
4 | * Example implementation of Factory method pattern
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class PaymentFactory {
10 |
11 | // Factory methods to return payment instance type
12 | public static Payment getInstance(PaymentOptions option) {
13 | return createPaymentType(option);
14 | }
15 |
16 | public static Payment getInstance() {
17 | return createPaymentType(null);
18 | }
19 |
20 | // Object instantiation logic
21 | private static Payment createPaymentType(PaymentOptions option) {
22 | if(option==null)
23 | return new CashPayment(); // default payment option
24 |
25 | switch(option) {
26 | case CASH:
27 | return new CashPayment();
28 | case CREDIT_CARD:
29 | return new CreditCardPayment();
30 | case NET_BANKING:
31 | return new NetbankingPayment();
32 | default:
33 | return new CashPayment(); // default payment option
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/factorymethod/PaymentOptions.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.factorymethod;
2 |
3 | /**
4 | * Constants for payment options
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public enum PaymentOptions {
10 | CASH, CREDIT_CARD, NET_BANKING;
11 | }
12 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/factorymethod/README.md:
--------------------------------------------------------------------------------
1 | # Factory Method Pattern
2 |
3 | To replace class constructors and abstract the process of object generation so that the type of the object instantiated can be determined at run-time.
4 |
5 | ## Usage / Concepts
6 |
7 | * Define a "virtual" constructor. Used to instantiate an object from one among a set of classes based on a logic.
8 | * Create object without exposing the creation logic to the client and refer to newly created object using a common interface.
9 | * Object instantiation logic should not be exposed to client. A client class will not know what classes it will be required to create.
10 |
11 | ## See it in Action / Sample Code Snippet
12 |
13 | * Factory method of Java Calendar and custom implementation of Payment use case.
14 | * Run [AppTestDrive.java](https://github.com/tirthalpatel/Learning-OOPD/blob/master/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/factorymethod/AppTestDrive.java) and refer the corresponding code flow.
15 | * Payment (interface) can have concrete implementations such as CashPayment, CreditCardPayment and NetbankingPayment.
16 | * PaymentFactory's factory method is responsible for creating instance of Payment as per supplied PaymentOption argument by client app.
17 |
18 | ## Key Design Considerations
19 |
20 | * Factory is responsible for object instantiation lifecycle. If applicable, consider designing an internal "object pool" that will allow objects to be reused instead of created from scratch.
21 | * Parameterized factory method - design the arguments to the factory method. What qualities or characteristics are necessary and sufficient to identify the correct derived class to instantiate?
22 | * If having an inheritance hierarchy that exercises polymorphism, consider adding a polymorphic creation capability by defining a static factory method in the base class.
23 |
24 | ## Real World Examples
25 |
26 | * [java.util.Calendar#getInstace()](https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#getInstance())
27 | * [java.util.ResourceBundle#getBundle()](https://docs.oracle.com/javase/7/docs/api/java/util/ResourceBundle.html#getBundle(java.lang.String))
28 | * [java.text.NumberFormat#getInstance()](https://docs.oracle.com/javase/7/docs/api/java/text/NumberFormat.html#getInstance())
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/objectpool/README.md:
--------------------------------------------------------------------------------
1 | # Object Pool Pattern
2 |
3 | To reuse the object that are expensive to create. Although the object pool is handling the object instantiation, it's main purpose is to provide a way for the clients to reuse the objects like they are new objects, without being shared.
4 |
5 | ## Usage / Concepts
6 |
7 | * When an application requires objects which are expensive to create. For example, there is a need of opening too many connections for the database then it takes too longer to create a new one and the database server will be overloaded.
8 | * When there are several clients who need the same resource at different times.
9 |
10 | ## See it in Action / Sample Code Snippet
11 |
12 | * [Creating Object Pool using Apache Commons Pool](https://dzone.com/articles/creating-object-pool-java)
13 |
14 | ## Key Design Considerations
15 |
16 | * An Object pool is a container which contains a specified amount of objects. When an object is taken from the pool, it is not available in the pool until it is put back.
17 | * Objects in the pool have a lifecycle: creation, validation and destroy.
18 |
19 | ## Hot Spots
20 |
21 | * When the Object Pool pattern is used the objects should be marked as available(released) by the client after they are used, so the pool will be aware about this. This is the main drawback because the client should do this and it's a common situation when database connection are not released after they are used. To overcome this a mechanism can be implemented to release resources, if they are not used for a period of time.
22 | * Creating the resources might fail and this case should be treated carefully. When there is no available resource (because the number is limited or creating a new one failed) the client should be notified about it.
23 |
24 | ## Real World Examples
25 |
26 | * Java supports thread pooling via java.util.concurrent.ExecutorService and other related classes
27 | * The data source pools and thread pools in application servers
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/prototype/AppTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.prototype;
2 |
3 | /**
4 | * Client app accessing implementations of prototype pattern example
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class AppTestDrive {
10 |
11 | public static void main(String[] args) {
12 |
13 | // Although a cloned copy, each instance is unique
14 |
15 | Shape clonedShape1 = (Shape) ShapeRegistry.getShape("1");
16 | System.out.println("Shape : " + clonedShape1);
17 |
18 | clonedShape1 = (Shape) ShapeRegistry.getShape("1");
19 | System.out.println("Shape : " + clonedShape1);
20 |
21 | clonedShape1 = (Shape) ShapeRegistry.getShape("1");
22 | System.out.println("Shape : " + clonedShape1);
23 |
24 | System.out.println("-----------");
25 |
26 | Shape clonedShape2 = (Shape) ShapeRegistry.getShape("2");
27 | System.out.println("Shape : " + clonedShape2);
28 |
29 | clonedShape2 = (Shape) ShapeRegistry.getShape("2");
30 | System.out.println("Shape : " + clonedShape2);
31 |
32 | System.out.println("-----------");
33 |
34 | Shape clonedShape3 = (Shape) ShapeRegistry.getShape("3");
35 | System.out.println("Shape : " + clonedShape3);
36 |
37 | clonedShape3 = (Shape) ShapeRegistry.getShape("3");
38 | System.out.println("Shape : " + clonedShape3);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/prototype/Circle.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.prototype;
2 |
3 | public class Circle extends Shape {
4 |
5 | public Circle() {
6 | type = "Circle";
7 | }
8 |
9 | @Override
10 | public void draw() {
11 | System.out.println("Inside Circle::draw() method.");
12 | }
13 | }
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/prototype/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/prototype/README.md
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/prototype/Rectangle.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.prototype;
2 |
3 | public class Rectangle extends Shape {
4 |
5 | public Rectangle() {
6 | type = "Rectangle";
7 | }
8 |
9 | @Override
10 | public void draw() {
11 | System.out.println("Inside Rectangle::draw() method.");
12 | }
13 | }
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/prototype/Shape.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.prototype;
2 |
3 | // An abstract class implementing Clonable interface
4 | public abstract class Shape implements Cloneable {
5 |
6 | private String id;
7 | protected String type;
8 |
9 | abstract void draw();
10 |
11 | public String getType() {
12 | return type;
13 | }
14 |
15 | public String getId() {
16 | return id;
17 | }
18 |
19 | public void setId(String id) {
20 | this.id = id;
21 | }
22 |
23 | public Object clone() {
24 | Object clone = null;
25 |
26 | try {
27 | clone = super.clone();
28 |
29 | } catch (CloneNotSupportedException e) {
30 | e.printStackTrace();
31 | }
32 |
33 | return clone;
34 | }
35 |
36 | @Override
37 | public String toString() {
38 | return super.toString() + " [id=" + id + ", type=" + type + "]";
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/prototype/ShapeRegistry.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.prototype;
2 |
3 | import java.util.Hashtable;
4 |
5 | /**
6 | * A registry / cache, which avoids costly object creation and provides cloned object
7 | *
8 | * @author tirthalp
9 | */
10 | public class ShapeRegistry {
11 |
12 | private static Hashtable shapesCache = new Hashtable();
13 |
14 | static {
15 | loadShapes();
16 | }
17 |
18 | public static Shape getShape(String shapeId) {
19 | Shape cachedShape = shapesCache.get(shapeId);
20 |
21 | // Typically avoid usage of "new". Rather returns unique instance as a cloned copy.
22 | return (Shape) cachedShape.clone();
23 | }
24 |
25 | /*
26 | * Assume, initial creation of each object is an expensive operation here. May be for each shape, it needs to run
27 | * database query.
28 | *
29 | * So instead of triggering that process every time, better to cache them using shapesCache.put(shapeKey, shape).
30 | */
31 | private static void loadShapes() {
32 | Circle circle = new Circle();
33 | circle.setId("1");
34 | shapesCache.put(circle.getId(), circle);
35 |
36 | Square square = new Square();
37 | square.setId("2");
38 | shapesCache.put(square.getId(), square);
39 |
40 | Rectangle rectangle = new Rectangle();
41 | rectangle.setId("3");
42 | shapesCache.put(rectangle.getId(), rectangle);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/prototype/Square.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.prototype;
2 |
3 | public class Square extends Shape {
4 |
5 | public Square() {
6 | type = "Square";
7 | }
8 |
9 | @Override
10 | public void draw() {
11 | System.out.println("Inside Square::draw() method.");
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/singleton/AppTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.singleton;
2 |
3 | /**
4 | * Client app accessing different implementations of singleton pattern for Logger example
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class AppTestDrive {
10 |
11 | public static void main(String[] args) {
12 |
13 | // --- Real world example - Java Runtime
14 | Runtime r1 = Runtime.getRuntime();
15 | Runtime r2 = Runtime.getRuntime();
16 | System.out.println(r1);
17 | System.out.println(r2);
18 | if(r1 == r2)
19 | System.out.println("'" + r1 + "' and '" + r2 + "' both are same.");
20 | System.out.println("-------------");
21 |
22 | // --- Custom singleton Logger instances
23 |
24 | // Option 1 - eager instantiation
25 | LoggerUsingEagerInstantiation.getInstance().print();
26 | LoggerUsingEagerInstantiation.getInstance().print();
27 | LoggerUsingEagerInstantiation.getInstance().print();
28 | LoggerUsingEagerInstantiation instance1 = LoggerUsingEagerInstantiation.getInstance();
29 | LoggerUsingEagerInstantiation instance2 = LoggerUsingEagerInstantiation.getInstance();
30 | if(instance1 == instance2)
31 | System.out.println("'" + instance1 + "' and '" + instance2 + "' both are same.");
32 | System.out.println("-------------");
33 |
34 | // Option 2 - lazy instantiation using double locking mechanism
35 | LoggerUsingLazyInstantiationDoubleLocking.getInstance().print();
36 | LoggerUsingLazyInstantiationDoubleLocking.getInstance().print();
37 | LoggerUsingLazyInstantiationDoubleLocking.getInstance().print();
38 | System.out.println("-------------");
39 |
40 | // Option 3 - simplify singleton implementation using inner class
41 | LoggerUsingInnerClass.getInstance().print();
42 | LoggerUsingInnerClass.getInstance().print();
43 | LoggerUsingInnerClass.getInstance().print();
44 | System.out.println("-------------");
45 |
46 | // Option 4 - singleton implementation using Java 5 enum
47 | LoggerUsingEnum.getInstance().print();
48 | LoggerUsingEnum.getInstance().print();
49 | LoggerUsingEnum.getInstance().print();
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/singleton/LoggerUsingEagerInstantiation.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.singleton;
2 |
3 | /**
4 | * Example code snippet of Logger class singleton pattern implementation for eager instantiation.
5 | *
6 | * @author tirthalp
7 | */
8 | public class LoggerUsingEagerInstantiation {
9 |
10 | private final static LoggerUsingEagerInstantiation m_instance = new LoggerUsingEagerInstantiation();
11 |
12 | // Private constructor prevents instantiation from other classes
13 | private LoggerUsingEagerInstantiation() {
14 | System.out.println("LoggerUsingEagerInstantiation(): Initializing Instance");
15 | }
16 |
17 | public static LoggerUsingEagerInstantiation getInstance() {
18 | return m_instance;
19 | }
20 |
21 | public void print() {
22 | System.out.println("Printing performed by object " + this);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/singleton/LoggerUsingEnum.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/singleton/LoggerUsingEnum.java
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/singleton/LoggerUsingInnerClass.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.singleton;
2 |
3 | /**
4 | * Example code snippet of Logger class singleton pattern implementation using inner class approach.
5 | *
6 | * @author tirthalp
7 | */
8 | public class LoggerUsingInnerClass {
9 |
10 | // Private constructor prevents instantiation from other classes
11 | private LoggerUsingInnerClass() {
12 | System.out.println("LoggerUsingInnerClass(): Initializing Instance");
13 | }
14 |
15 | /*
16 | * The inner class is referenced no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is called.
17 | * Thus, this solution is thread-safe without requiring special language constructs (i.e. volatile or synchronized).
18 | *
19 | * To sum up, LoggerHolder is loaded on the first execution of LoggerUsingInnerClass.getInstance() or the first access to LoggerHolder.INSTANCE,
20 | * not before.
21 | */
22 | private static class LoggerHolder {
23 | private static final LoggerUsingInnerClass INSTANCE = new LoggerUsingInnerClass();
24 | }
25 |
26 | public static LoggerUsingInnerClass getInstance() {
27 | return LoggerHolder.INSTANCE;
28 | }
29 |
30 | public void print() {
31 | System.out.println("Printing performed by object " + this);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/singleton/LoggerUsingLazyInstantiationDoubleLocking.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.creational.singleton;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * Example code snippet of Logger class singleton pattern implementation for lazy instantiation using double locking mechanism.
7 | *
8 | * @author tirthalp
9 | */
10 | public class LoggerUsingLazyInstantiationDoubleLocking implements Serializable {
11 | private static final long serialVersionUID = 1L;
12 | private static LoggerUsingLazyInstantiationDoubleLocking m_instance;
13 |
14 | // Private constructor prevents instantiation from other classes
15 | private LoggerUsingLazyInstantiationDoubleLocking() {
16 | System.out.println("LoggerUsingLazyInstantiationDoubleLocking(): Initializing Instance");
17 | }
18 |
19 | /*
20 | * The singleton instance is created when the getInstance() method is called for the first time. This is called lazy instantiation and it ensures
21 | * that the singleton instance is created only when it is needed.
22 | */
23 | public static LoggerUsingLazyInstantiationDoubleLocking getInstance() {
24 | if (m_instance == null) {
25 | synchronized (LoggerUsingLazyInstantiationDoubleLocking.class) {
26 | if (m_instance == null) {
27 | System.out.println("getInstance(): First time getInstance was invoked!");
28 | m_instance = new LoggerUsingLazyInstantiationDoubleLocking();
29 | }
30 | }
31 | }
32 |
33 | return m_instance;
34 | }
35 |
36 | /*
37 | * When Singletons are implementing Serializable interface they have to implement readResolve method in order to avoid having 2 different objects.
38 | * This method is called immediately after an object of this class is deserialized. This method returns the singleton instance.
39 | */
40 | protected Object readResolve() {
41 | return getInstance();
42 | }
43 |
44 | public void print() {
45 | System.out.println("Printing performed by object " + this);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/singleton/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPatterns/src/com/tirthal/learning/design/patterns/creational/singleton/README.md
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/README.md
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/adapter/AppTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.adapter;
2 |
3 | import java.util.Arrays;
4 | import java.util.List;
5 |
6 | /**
7 | * Client app for demo of adapter pattern
8 | *
9 | * @author tirthalp
10 | *
11 | */
12 | public class AppTestDrive {
13 |
14 | public static void main(String args[]) {
15 |
16 | // --- Real world example - Arrays.asList : convert Arrays -> List
17 | String[] colorsArray = new String[]{"red", "blue", "white", "black"};
18 | List colorsList = Arrays.asList(colorsArray);
19 | System.out.println(colorsArray + " -> " + colorsList);
20 | System.out.println("---------------------------");
21 |
22 | // --- Custom Adapter pattern example
23 | String input = "Hello world 1. Hello world 2. Hello world 3. Hello world 4. Hello world 5. ";
24 |
25 | TextFormattable tf = new NewlineFormatter();
26 | System.out.println(tf.formatText(input, ". "));
27 |
28 | // tf = new CsvFormatter(); // Obviously incompatible interface, so need adaptor
29 | tf = new CsvAdapterImpl(new CsvFormatter());
30 | System.out.println(tf.formatText(input, "."));
31 |
32 | // Likewise, there could be multiple adaptors as per need
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/adapter/CsvAdapterImpl.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.adapter;
2 |
3 | /**
4 | * An example adapter class that adapts the Adaptee to the Target
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class CsvAdapterImpl implements TextFormattable {
10 |
11 | private CsvFormatter cf;
12 |
13 | public CsvAdapterImpl(CsvFormatter cf) {
14 | this.cf = cf;
15 | }
16 |
17 | @Override
18 | public String formatText(String text, String separator) {
19 |
20 | return cf.formatCsvText(text, separator);
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/adapter/CsvFormattable.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.adapter;
2 |
3 | /**
4 | * An example of incompatible interface that needs adapting
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public interface CsvFormattable {
10 |
11 | String formatCsvText(String text, String separator);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/adapter/CsvFormatter.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.adapter;
2 |
3 | public class CsvFormatter implements CsvFormattable {
4 |
5 | @Override
6 | public String formatCsvText(String text, String separator) {
7 |
8 | if (text != null && separator != null)
9 | return text.replace(separator, ",");
10 |
11 | return null;
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/adapter/NewlineFormatter.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.adapter;
2 |
3 | public class NewlineFormatter implements TextFormattable {
4 |
5 | @Override
6 | public String formatText(String text, String separator) {
7 |
8 | if (text != null && separator != null)
9 | return text.replace(separator, "\n");
10 |
11 | return null;
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/adapter/README.md:
--------------------------------------------------------------------------------
1 | # Adapter Pattern
2 |
3 | To act as an intermediary between two classes, converting the interface of one class so that it can be used with the other. Often designed to integrate new client with old/legacy components.
4 |
5 | ## Usage / Concepts
6 |
7 | * Use when an object needs to utilize an existing class with an incompatible interface.
8 | * Permits classes with disparate interfaces to work together by creating a common object by which they may communicate and interact.
9 | * Convert interface into another interface - for making things working after code is designed or specifically dealing with legacy code.
10 | * Retrofit to make unrelated classes work together or translate requests.
11 |
12 | ## See it in Action / Sample Code Snippet
13 |
14 | * Java Arrays.asList and custom adapter pattern example.
15 | * Run [AppTestDrive.java](https://github.com/tirthalpatel/Learning-OOPD/blob/master/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/adapter/AppTestDrive.java) client and refer the corresponding code flow.
16 | * TextFormattable: Target
17 | * CsvFormattable: Adaptee
18 | * CsvAdapterImpl: Adapter
19 |
20 | ## Key Design Considerations
21 |
22 | Adapter makes things work after they're designed. The classes/objects participating in adapter pattern:
23 |
24 | * Target: defines the domain-specific interface that Client uses.
25 | * Adapter: adapts the interface Adaptee to the Target interface.
26 | * Adaptee: defines an existing interface that needs adapting.
27 | * Client: collaborates with objects conforming to the Target interface.
28 |
29 | ## Real World Examples
30 |
31 | * [Arrays -> List](https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#asList(T...))
32 | * Java IO Streams
33 | * Spring Integration uses JMS adapters to send and receive JMS messages and JDBC adapters to convert messages to database queries and result sets back to messages.
34 | * Non software examples: power supply adapters, card readers and adapters, etc.
35 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/adapter/TextFormattable.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.adapter;
2 |
3 | /**
4 | * An example of the target interface that clients communicate with
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public interface TextFormattable {
10 |
11 | String formatText(String text, String separator);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/bridge/AppTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.bridge;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * Client app for demo of bridge pattern
8 | *
9 | * @author tirthalp
10 | *
11 | */
12 | public class AppTestDrive {
13 |
14 | public static void main(String[] args) {
15 |
16 | // --- Custom example of bridge between Vehicle abstractions and Workshop concrete implementations
17 |
18 | List workshops = new ArrayList<>();
19 | workshops.add(new Produce());
20 | workshops.add(new Assemble());
21 |
22 | Vehicle vehicle1 = new Car(workshops);
23 | vehicle1.manufacture();
24 | Vehicle vehicle2 = new Bike(workshops);
25 | vehicle2.manufacture();
26 |
27 | // How abstractions and implementations can be independently extensible?
28 | // Try adding 'Truck extends Vehicle' or 'QualityAudit extends Workshop' independently.
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/bridge/Assemble.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.bridge;
2 |
3 | /**
4 | * an example Concrete implementation 2 for bridge pattern
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Assemble implements Workshop {
10 |
11 | @Override
12 | public void work() {
13 | System.out.println("-> Assembled ");
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/bridge/Bike.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.bridge;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * An example of Refined abstraction 2 in bridge pattern
7 | *
8 | * @author tirthalp
9 | *
10 | */
11 | public class Bike extends Vehicle {
12 |
13 | public Bike(List workShops) {
14 | super(workShops);
15 | }
16 |
17 | @Override
18 | public String getVehicleType() {
19 | return "Bike ";
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/bridge/Car.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.bridge;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * An example of Refined abstraction 1 in bridge pattern
7 | *
8 | * @author tirthalp
9 | *
10 | */
11 | public class Car extends Vehicle {
12 |
13 | public Car(List workShops) {
14 | super(workShops);
15 | }
16 |
17 | @Override
18 | public String getVehicleType() {
19 | return "Car ";
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/bridge/Produce.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.bridge;
2 |
3 | /**
4 | * An example Concrete implementation 1 for bridge pattern
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Produce implements Workshop {
10 |
11 | @Override
12 | public void work() {
13 | System.out.print("-> Produced ");
14 | }
15 | }
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/bridge/README.md:
--------------------------------------------------------------------------------
1 | # Bridge Pattern
2 |
3 | To separate the abstract elements of a class from the implementation details, providing the means to replace the implementation details without modifying the abstraction.
4 |
5 | ## Usage / Concepts
6 |
7 | Decouples the functional abstraction from the implementation so that the two can vary independently. Use when,
8 |
9 | * Abstractions and implementations should not be bound at compile time.
10 | * Abstractions and implementations should be independently extensible.
11 | * Changes in the implementation of an abstraction should have no impact on clients.
12 | * Implementation details should be hidden from the client.
13 |
14 | ## See it in Action / Sample Code Snippet
15 |
16 | * Run [AppTestDrive.java](https://github.com/tirthalpatel/Learning-OOPD/blob/master/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/bridge/AppTestDrive.java) client and refer the corresponding code flow.
17 | * Vehicle: Abstraction, which contains reference to the implementer.
18 | * Car, Bike: Refined Abstraction.
19 | * Workshop: Implementer.
20 | * Assemble, Produce: Concrete Implementation of the Implementer.
21 | * Abstractions and implementations can be independently extensible, i.e., add 'Truck extends Vehicle' or 'QualityAudit extends Workshop' independently.
22 | * see [Before Bridge Design Pattern vs. After Bridge Design Pattern](http://javapapers.com/design-patterns/bridge-design-pattern/)
23 |
24 | ## Key Design Considerations
25 |
26 | * Create two different hierarchies. One for abstraction and another for implementation. Create a bridge that coordinates between abstraction and implementation.
27 | * Avoid permanent binding by removing the dependency between abstraction and implementation. Decouple abstraction and implementation using Encapsulation, Composition and Inheritance techniques.
28 | * Abstraction and implementation can be extended separately. Should be used when we have need to switch implementation at runtime.
29 | * Client should not be impacted, if there is modification in implementation of abstraction.
30 | * The classes/objects participating in bridge pattern:
31 | * Abstraction: Core of the bridge design pattern and defines the crux. Contains a reference to the implementer.
32 | * Refined Abstraction: Extends the abstraction takes the finer detail one level below. Hides the finer elements from implementers.
33 | * Implementer: This interface is the higher level than abstraction. Just defines the basic operations.
34 | * Concrete Implementation: Implements the above implementer by providing concrete implementation.
35 |
36 | ## Real World Examples
37 |
38 | * JDBC Drivers
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/bridge/Vehicle.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.bridge;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * An example of abstraction in bridge pattern
7 | *
8 | * @author tirthalp
9 | *
10 | */
11 | public abstract class Vehicle {
12 | protected List workshops;
13 |
14 | protected Vehicle(List workshops) {
15 | this.workshops = workshops;
16 | }
17 |
18 | public void manufacture() {
19 | System.out.print(getVehicleType());
20 |
21 | for(Workshop workshop : workshops) {
22 | workshop.work();
23 | }
24 | }
25 |
26 | abstract public String getVehicleType();
27 | }
28 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/bridge/Workshop.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.bridge;
2 |
3 | /**
4 | * An example of Implementor for bridge pattern
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public interface Workshop {
10 |
11 | abstract public void work();
12 | }
13 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/composite/AppTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.composite;
2 |
3 | /**
4 | * Client app for demo of composite pattern
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class AppTestDrive {
10 |
11 | public static void main(String[] args) {
12 |
13 | // --- Custom example hierarchical representations of Menu
14 |
15 | MenuComponent home = new Menu("Home", "/");
16 |
17 | MenuComponent products = new Menu("Products", "/all-products");
18 | products.add(new MenuItem("Product-1", "/p1"));
19 | products.add(new MenuItem("Product-1", "/p1"));
20 | home.add(products);
21 |
22 | MenuComponent contact = new MenuItem("Contact", "/contact");
23 | home.add(contact);
24 |
25 | System.out.println(home.toString());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/composite/Menu.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.composite;
2 |
3 | import java.util.Iterator;
4 |
5 | /**
6 | * An example of Composite in composite pattern.
7 | *
8 | * @author tirthalp
9 | *
10 | */
11 | public class Menu extends MenuComponent {
12 |
13 | public Menu(String name, String url) {
14 | this.name = name;
15 | this.url = url;
16 | }
17 |
18 | public MenuComponent add(MenuComponent menuComponent) {
19 | menuComponents.add(menuComponent);
20 | return menuComponent;
21 | }
22 |
23 | public MenuComponent remove(MenuComponent menuComponent) {
24 | menuComponents.remove(menuComponent);
25 | return menuComponent;
26 | }
27 |
28 | @Override
29 | public String toString() {
30 |
31 | StringBuilder sb = new StringBuilder();
32 | sb.append(print(this));
33 |
34 | Iterator itr = menuComponents.iterator();
35 | while (itr.hasNext()) {
36 | MenuComponent mc = itr.next();
37 | sb.append(mc.toString());
38 | }
39 |
40 | return sb.toString();
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/composite/MenuComponent.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.composite;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * An example of Component in composite pattern.
8 | *
9 | * @author tirthalp
10 | *
11 | */
12 | public abstract class MenuComponent {
13 |
14 | List menuComponents = new ArrayList();
15 | String name;
16 | String url;
17 |
18 | public String getName() {
19 | return name;
20 | }
21 |
22 | public String getUrl() {
23 | return url;
24 | }
25 |
26 | public abstract String toString();
27 |
28 | public MenuComponent add(MenuComponent menuComponent) {
29 | throw new UnsupportedOperationException("This feature is not implemented at this level.");
30 | }
31 |
32 | public MenuComponent remove(MenuComponent menuComponent) {
33 | throw new UnsupportedOperationException("This feature is not implemented at this level.");
34 | }
35 |
36 | public String print(MenuComponent menuComponent) {
37 | return new StringBuilder(name).append(" : ").append(url).append("\n").toString();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/composite/MenuItem.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.composite;
2 |
3 | /**
4 | * An example of Leaf in composite pattern.
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class MenuItem extends MenuComponent {
10 |
11 | public MenuItem(String name, String url) {
12 | this.name = name;
13 | this.url = url;
14 | }
15 |
16 | @Override
17 | public String toString() {
18 | return print(this);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/composite/README.md:
--------------------------------------------------------------------------------
1 | # Composite Pattern
2 |
3 | To create hierarchical, recursive tree structures of related objects where any element of the structure may be accessed and utilized in a standard manner.
4 |
5 | ## Usage / Concepts
6 |
7 | * Facilitates the creation of object hierarchies where each object can be treated independently or as a set of nested objects through the same interface.
8 | * Use when,
9 | - Hierarchical representations of objects are needed.
10 | - Objects and compositions of objects should be treated uniformly.
11 |
12 | ## See it in Action / Sample Code Snippet
13 |
14 | * Run [AppTestDrive.java](https://github.com/tirthalpatel/Learning-OOPD/blob/master/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/composite/AppTestDrive.java) client and refer the corresponding code flow.
15 | * MenuComponent: Component.
16 | * MenuItem: Leaf.
17 | * Menu: Composite.
18 |
19 | ## Key Design Considerations
20 |
21 | * Tree structured - Component, Leaf, Composite, in which Leaf and Composite have the same interface
22 | * The classes/objects participating in composite pattern:
23 | * Component: Declares interface for objects in composition; Implements default behavior for the interface common to all classes as appropriate; Declares an interface for accessing and managing its child components.
24 | * Leaf: Represents leaf objects in composition; A leaf has no children; Defines behavior for primitive objects in the composition.
25 | * Composite: Defines behavior for components having children; Stores child component; Implements child related operations in the component interface.
26 | * Client: Manipulates objects in the composition through the component interface.
27 |
28 | ## Real World Examples
29 |
30 | * [java.awt.Component#add(Component)](https://docs.oracle.com/javase/7/docs/api/java/awt/Container.html#add(java.awt.Component))
31 | * JSF Widgets
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/decorator/AppTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.decorator;
2 |
3 | import java.io.DataOutputStream;
4 | import java.io.File;
5 | import java.io.FileOutputStream;
6 | import java.io.IOException;
7 | import java.io.OutputStream;
8 |
9 | /**
10 | * Client app for demo of decorator pattern to prepare beverage with choice of condiments
11 | *
12 | * @author tirthalp
13 | *
14 | */
15 | public class AppTestDrive {
16 |
17 | public static void main(String args[]) throws IOException {
18 |
19 | // --- Real world example - OutputStream
20 |
21 | File f = new File("./target/temp.txt");
22 | f.createNewFile();
23 |
24 | OutputStream os = new FileOutputStream(f);
25 | DataOutputStream dos = new DataOutputStream(os);
26 | dos.writeChars("Hello World!");
27 | dos.close();
28 |
29 | // --- Custom decorator patter example
30 |
31 | // Select type of beverage
32 | Beverage beverage = new RedTea();
33 |
34 | // Decorate with condiments like milk, sugar, tea masala...
35 | beverage = new Milk(beverage);
36 | beverage = new Sugar(beverage);
37 | beverage = new TeaMasala(beverage);
38 |
39 | // Print beverage and opted condiments description along with total price
40 | System.out.println("Total cost of '" + beverage.getDescription() + "' = Rs. " + beverage.cost());
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/decorator/Beverage.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.decorator;
2 |
3 | /**
4 | * Beverage is supertype, which will offer each subclass concreate components to be used on its own, or wrapped by decorator component
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public abstract class Beverage {
10 |
11 | String description = "Unknown Beverage";
12 |
13 | public String getDescription() {
14 | return description;
15 | }
16 |
17 | // enforce to implement cost method in the sub class
18 | public abstract double cost();
19 | }
20 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/decorator/CondimentDecorator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.decorator;
2 |
3 | /**
4 | * This is abstract class for decorators. It extends Beverage, because we need to be interchangeable with a Beverage.
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public abstract class CondimentDecorator extends Beverage {
10 |
11 | // enforce to implement getDescription method in the condiments sub classes
12 | public abstract String getDescription();
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/decorator/Milk.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.decorator;
2 |
3 | /**
4 | * Milk is-a type of condiment, which is example of the concrete decorator class.
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Milk extends CondimentDecorator {
10 |
11 | // An instance variable to hold the beverage we are wrapping
12 | Beverage beverage;
13 |
14 | // A way to set this instance variable to the object we are wrapping
15 | public Milk(Beverage beverage) {
16 | this.beverage = beverage;
17 | }
18 |
19 | // First delegate to the object we are decorating get its description, and then append description for this condiment
20 | public String getDescription() {
21 | return beverage.getDescription() + ", Milk";
22 | }
23 |
24 | // First we delegate the call to the object we're decorating, so that it can compute the cost, and then add the cost of this condiment to the result
25 | public double cost() {
26 | return beverage.cost() + 1.00;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/decorator/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/decorator/README.md
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/decorator/RedTea.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.decorator;
2 |
3 | /**
4 | * Rea Tea is-a type of beverage.
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class RedTea extends Beverage {
10 |
11 | public RedTea() {
12 | description = "Red Tea";
13 | }
14 |
15 | public double cost() {
16 | return 5.00;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/decorator/Sugar.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.decorator;
2 |
3 | /**
4 | * Sugar is-a type of condiment, which is example of the concrete decorator class.
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Sugar extends CondimentDecorator {
10 |
11 | // An instance variable to hold the beverage we are wrapping
12 | Beverage beverage;
13 |
14 | // A way to set this instance variable to the object we are wrapping
15 | public Sugar(Beverage beverage) {
16 | this.beverage = beverage;
17 | }
18 |
19 | // First delegate to the object we are decorating get its description, and then append description for this condiment
20 | public String getDescription() {
21 | return beverage.getDescription() + ", Sugar";
22 | }
23 |
24 | // First we delegate the call to the object we're decorating, so that it can compute the cost, and then add the cost of this condiment to the result
25 | public double cost() {
26 | return beverage.cost() + 1.00;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/DesignPatterns/src/com/tirthal/learning/design/patterns/structural/decorator/TeaMasala.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.design.patterns.structural.decorator;
2 |
3 | /**
4 | * Tea Masala is-a type of condiment, which is example of the concrete decorator class.
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class TeaMasala extends CondimentDecorator {
10 |
11 | // An instance variable to hold the beverage we are wrapping
12 | Beverage beverage;
13 |
14 | // A way to set this instance variable to the object we are wrapping
15 | public TeaMasala(Beverage beverage) {
16 | this.beverage = beverage;
17 | }
18 |
19 | // First delegate to the object we are decorating get its description, and then append description for this condiment
20 | public String getDescription() {
21 | return beverage.getDescription() + ", Tea Masala";
22 | }
23 |
24 | // First we delegate the call to the object we're decorating, so that it can compute the cost, and then add the cost of this condiment to the result
25 | public double cost() {
26 | return beverage.cost() + 1.00;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/DesignPrinciples/.gitignore:
--------------------------------------------------------------------------------
1 | /.settings/
2 | /target/
3 | /.classpath
4 | /.project
5 |
--------------------------------------------------------------------------------
/DesignPrinciples/README.md:
--------------------------------------------------------------------------------
1 | Learn OOP Design Principles
2 | ===========================
3 |
4 | This project is created for sharing sample java code (by practical examples along with easy to understand comments) to learn object oriented programming concepts and design principles.
5 |
6 | How to use? - Just import this project in Eclipse an "Existing Maven Project". If require, do necessary configuration to fix build path errors (e.g. setup JRE 1.8).
7 |
8 | For more detail, please read [here](http://tirthalpatel.blogspot.in/2014/01/oop-design-fundamentals-and-principles.html)
9 |
10 |
11 | Object oriented programming concepts
12 | ------------------------------------
13 |
14 | Refer package - [com.tirthal.learning.oop.concepts](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPrinciples/src/com/tirthal/learning/oop/concepts)
15 |
16 | For more detail, please read [here](http://tirthalpatel.blogspot.in/2014/01/oop-design-part-1-fundamentals.html)
17 |
18 |
19 | Class design principles - SOLID
20 | --------------------------------
21 |
22 | Refer package - [com.tirthal.learning.oop.design.principles.clazz.solid](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid)
23 |
24 | For more detail, please read [here](http://tirthalpatel.blogspot.in/2014/04/oop-design-part-2-class-principles-solid.html)
25 |
26 |
27 | Class design principles - GRASP
28 | -------------------------------
29 |
30 | Refer package - com.tirthal.learning.oop.design.principles.clazz.grasp
31 |
32 | TODO - To be added...
33 |
34 |
35 | Package design principles
36 | -------------------------
37 |
38 | Refer package - com.tirthal.learning.oop.design.principles.package
39 |
40 | TODO - To be added...
--------------------------------------------------------------------------------
/DesignPrinciples/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 | DesignPrinciples
6 | DesignPrinciples
7 | jar
8 | 0.0.1-SNAPSHOT
9 | Sample code snippet to learn object oriented programming concepts and design principles
10 |
11 |
12 | src
13 |
14 |
15 | org.apache.maven.plugins
16 | maven-compiler-plugin
17 | 2.3.2
18 |
19 | 1.8
20 | 1.8
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/README.md:
--------------------------------------------------------------------------------
1 | For more detail, please read [here](http://tirthalpatel.blogspot.in/2014/01/oop-design-fundamentals-and-principles.html)
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/concepts/AggregationComposition_TestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.concepts;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | //---------------------------------------
7 | //--- STEP 00 - WHAT IS AGGREGATION & COMPOSITION?
8 | //---------------------------------------
9 |
10 | ///**
11 | // * Aggregation = HAS-A Relationship.
12 | // *
13 | // * Aggregation is an association represents a part of a whole relationship where a part can exist without a whole.
14 | // * It has a weaker relationship. For example, If line-item HAS-A product, then a line item is a whole and product is a part.
15 | // * If a line item is deleted, then corresponding product needs not to be deleted.
16 | // */
17 |
18 | ///**
19 | // * Composition = HAS-A relationship, but restricted form of Aggregation
20 | // *
21 | // * Composition is an association represents a part of a whole relationship where a part cannot exist without a whole. If a whole is deleted then
22 | // * all parts are deleted. It has a stronger relationship. For example, if order HAS-A line-items, then an order is a whole and line items are parts.
23 | // * If an order is deleted then all corresponding line items for that order should be deleted.
24 | // */
25 |
26 | // ---------------------------------------
27 | // --- STEP 01 - UNDERSTAND AGGREGATION & COMPOSITION BY EXAMPLE
28 | // ---------------------------------------
29 |
30 | /**
31 | * This is test class for aggregation and composition example
32 | *
33 | * @author tirthalp
34 | *
35 | */
36 | public class AggregationComposition_TestDrive {
37 | public static void main(String[] args) {
38 | // Create Products
39 | Product p1 = new Product(1, "Pen", "This is red pen");
40 | Product p2 = new Product(2, "Pencil", "This is pencil");
41 | Product p3 = new Product(3, "ColorBox", "This is color box");
42 |
43 | // Create Order and Add Line Items
44 | Order o = new Order(1, "ORD#1");
45 | o.addItem(1, 2, p1); // Ordered of 2 quantity for p1 product
46 | o.addItem(2, 1, p2); // Ordered of 1 quantity for p2 product
47 | o.addItem(3, 5, p3); // Ordered of 5 quantity for p3 product
48 | // Print Order detail before deleting
49 | System.out.println("Order ---");
50 | System.out.println(o);
51 | // Deleting order would also delete associated LineItems ------- Represents Composition relationship between Order and LineItem
52 | o = null;
53 | // Line items are deleted, but associated products can still exist -------- Represents Aggregation relationship between LineItem and Product
54 | System.out.println("Products ---");
55 | System.out.println(p1);
56 | System.out.println(p2);
57 | System.out.println(p3);
58 | }
59 | }
60 |
61 | /**
62 | * This is Product class
63 | *
64 | * @author tirthalp
65 | *
66 | */
67 | class Product {
68 | private int id;
69 | private String name;
70 | private String description;
71 |
72 | public Product(int id, String name, String description) {
73 | super();
74 | this.id = id;
75 | this.name = name;
76 | this.description = description;
77 | }
78 | public int getId() {
79 | return id;
80 | }
81 | public void setId(int id) {
82 | this.id = id;
83 | }
84 | public String getName() {
85 | return name;
86 | }
87 | public void setName(String name) {
88 | this.name = name;
89 | }
90 | public String getDescription() {
91 | return description;
92 | }
93 | public void setDescription(String description) {
94 | this.description = description;
95 | }
96 | @Override
97 | public String toString() {
98 | return "Product [id=" + id + ", name=" + name + ", description=" + description + "]";
99 | }
100 | }
101 |
102 | /**
103 | * This is LineItem class, which HAS-A aggregation association with Product class. That means, if you delete LineItem, then associated Product can
104 | * exist.
105 | *
106 | * @author tirthalp
107 | *
108 | */
109 | class LineItem {
110 | private int id;
111 | private int quantity;
112 | private Product p;
113 |
114 | public LineItem(int id, int quantity, Product p) {
115 | super();
116 | this.id = id;
117 | this.quantity = quantity;
118 | this.p = p;
119 | }
120 | public int getId() {
121 | return id;
122 | }
123 | public void setId(int id) {
124 | this.id = id;
125 | }
126 | public int getQuantity() {
127 | return quantity;
128 | }
129 | public void setQuantity(int quantity) {
130 | this.quantity = quantity;
131 | }
132 | public Product getP() {
133 | return p;
134 | }
135 | public void setP(Product p) {
136 | this.p = p;
137 | }
138 | @Override
139 | public String toString() {
140 | return "LineItem [id=" + id + ", quantity=" + quantity + ", p=" + p + "]";
141 | }
142 | }
143 |
144 | /**
145 | * This is Order class, which HAS-A composition association with LineItem class. That means if you delete Order, then associated all LineItem must be
146 | * deleted.
147 | *
148 | * @author tirthalp
149 | *
150 | */
151 | class Order {
152 | private int id;
153 | private String name;
154 | private List lineItems;
155 |
156 | public Order(int id, String name) {
157 | super();
158 | this.id = id;
159 | this.name = name;
160 | this.lineItems = new ArrayList();
161 | }
162 | public int getId() {
163 | return id;
164 | }
165 | public void setId(int id) {
166 | this.id = id;
167 | }
168 | public String getName() {
169 | return name;
170 | }
171 | public void setName(String name) {
172 | this.name = name;
173 | }
174 |
175 | @Override
176 | public String toString() {
177 | return "Order [id=" + id + ", name=" + name + ", lineItems=" + lineItems + "]";
178 | }
179 |
180 | // Add line item to order
181 | public void addItem(int id, int quantity, Product p) {
182 | this.lineItems.add(new LineItem(id, quantity, p));
183 | }
184 |
185 | // Remove line item from order for given item id
186 | public void removeItemById(int itemId) {
187 | // TODO - Not implemented yet
188 | }
189 | }
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/concepts/Cohesion_TestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.concepts;
2 |
3 | //---------------------------------------
4 | //--- STEP 00 - WHAT IS HIGH COHESION?
5 | //---------------------------------------
6 |
7 | ///**
8 | // * High Cohesion = The responsibilities/methods are highly related to class/module.
9 | // *
10 | // * The term cohesion is used to indicate the degree to which a class has a single, well-focused. Cohesion is a measure of how the methods of a class
11 | // * or a module are meaningfully and strongly related and how focused they are in providing a well-defined purpose to the system. The more focused a
12 | // * class is, the higher its cohesiveness - a good thing.
13 | // *
14 | // * A class is identified as a low cohesive class, when it contains many unrelated functions within it. And that what we need to avoid, because big
15 | // * classes with unrelated functions hamper their maintaining. Always make your class small and with precise purpose and highly related functions.
16 | // */
17 |
18 | //---------------------------------------
19 | //--- STEP 01 - EXAMPLE OF LOW COHESIVE CLASS
20 | //---------------------------------------
21 |
22 | /**
23 | * The purpose of "MyReader" is to read the resource. But it contains some unrelated functions such as validateLocation(), checkFTP(), ping(). Hence
24 | * it is low cohesive.
25 | *
26 | * @author tirthalp
27 | *
28 | */
29 | class MyReader_LowCohesive {
30 |
31 | // -------------- unrelated functions
32 |
33 | public boolean validateLocation(String pathIP) {
34 | return ping(pathIP) && checkFTP(pathIP);
35 | }
36 |
37 | private boolean checkFTP(String pathIP) {
38 | // TODO Add logic
39 | return true;
40 | }
41 |
42 | private boolean ping(String pathIP) {
43 | // TODO Add logic
44 | return true;
45 | }
46 |
47 | // -------------- functions related to read resource
48 |
49 | // read the resource from disk
50 | public String readFromDisk(String fileName) {
51 | return "data of " + fileName;
52 | }
53 |
54 | // read the resource from web
55 | public String readFromWeb(String url) {
56 | return "data of " + url;
57 | }
58 |
59 | // read the resource from network
60 | public String readFromNetwork(String networkAddress) {
61 | return "data of " + networkAddress;
62 | }
63 |
64 | }
65 |
66 | // ---------------------------------------
67 | // --- STEP 02 - EXAMPLE OF HIGH COHESIVE CLASS
68 | // ---------------------------------------
69 |
70 | /**
71 | * The purpose of "MyReader" is to read the resource and it does that only. It does not implement other unrelated things. Hence it is highly cohesive.
72 | *
73 | * @author tirthalp
74 | *
75 | */
76 | class MyReader_HighCohesive {
77 | // -------------- functions related to read resource
78 |
79 | // read the resource from disk
80 | public String readFromDisk(String fileName) {
81 | return "reading data of " + fileName;
82 | }
83 |
84 | // read the resource from web
85 | public String readFromWeb(String url) {
86 | return "reading data of " + url;
87 | }
88 |
89 | // read the resource from network
90 | public String readFromNetwork(String networkAddress) {
91 | return "reading data of " + networkAddress;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/concepts/Delegation_InsteadOfGetterSetter_TestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.concepts;
2 |
3 | //---------------------------------------
4 | //--- STEP 00 - LEARN DESIGN PRINCIPLE TO DEFINE BEHAVIOR
5 | //---------------------------------------
6 |
7 | // To define behavior, always consider to use "delegation" over offer data access via getter/setter methods
8 |
9 | //---------------------------------------
10 | //--- STEP 01 - UNDERSTAND DELEGATION OVER GETTER/SETTER APPROACH BY EXAMPLE
11 | //---------------------------------------
12 |
13 | /**
14 | *
15 | *
16 | * @author tirthalp
17 | * @see Delegation_TestDrive
18 | */
19 | public class Delegation_InsteadOfGetterSetter_TestDrive {
20 |
21 | public static void main(String[] args) {
22 | // -----------------------
23 | // --- STEP 03 - See why getter/setter are evil?
24 | // -----------------------
25 | Temperature1 temp1 = new Temperature1(100.0, TemperatureUnit.FAHRENHEIT);
26 | Temperature1 temp2 = new Temperature1(36.888, TemperatureUnit.CELSIUS);
27 |
28 | // Let's do something, if temp1 is higher than temp2
29 | double temp1InCelsius = ((temp1.getValue() - 32) * 5) / 9; // normalize to celsius
30 | double temp2InCelsius = temp2.getValue();
31 |
32 | if (temp1InCelsius > temp2InCelsius)
33 | System.out.println("Do some client specific operation...");
34 |
35 | /*
36 | * What's problem?
37 | *
38 | * Well, client code will become big and complex as need to add more functionality like adding Kelvin in
39 | * TemperatureUnit.
40 | *
41 | * Ideally, the Temperature1 class has the information, so it should be doing the comparison as per Delegation
42 | * principle. So getting the temperature value and doing comparison outside of the Temperature1 class is not at
43 | * all an acceptable solution.
44 | */
45 |
46 | // -----------------------
47 | // --- STEP 04 - See how delegation helps to solve above problem and simply client code?
48 | // -----------------------
49 | Temperature2 temp3 = new Temperature2(100.0, TemperatureUnit.FAHRENHEIT);
50 | Temperature2 temp4 = new Temperature2(36.888, TemperatureUnit.CELSIUS);
51 |
52 | if (temp3.isGreaterThan(temp4))
53 | System.out.println("Do some client specific operation...");
54 |
55 | /*
56 | * Awesome, this is greatly simplified client code.
57 | *
58 | * Learning = Temperature2 class has data, client code should delegate temperature normalization and comparison
59 | * responsibility to the Temperature2 class. Adding Kelvin support in TemperatureUnit would not impact client
60 | * code anymore.
61 | */
62 | }
63 | }
64 |
65 | // An enum of temperature units
66 | enum TemperatureUnit {
67 | CELSIUS, FAHRENHEIT;
68 | }
69 |
70 | // A class with getter/setter
71 | class Temperature1 {
72 | private double value;
73 | private TemperatureUnit unit;
74 |
75 | public Temperature1(double value, TemperatureUnit unit) {
76 | this.value = value;
77 | this.unit = unit;
78 | }
79 |
80 | public double getValue() {
81 | return value;
82 | }
83 |
84 | public void setValue(double value) {
85 | this.value = value;
86 | }
87 |
88 | public TemperatureUnit getUnit() {
89 | return unit;
90 | }
91 |
92 | public void setUnit(TemperatureUnit unit) {
93 | this.unit = unit;
94 | }
95 | }
96 |
97 | // A class having temperature comparison behavior, as it has data to do this job
98 | class Temperature2 {
99 | private double value;
100 | private TemperatureUnit unit;
101 |
102 | public Temperature2(double value, TemperatureUnit unit) {
103 | this.value = value;
104 | this.unit = unit;
105 | }
106 |
107 | public boolean isGreaterThan(Temperature2 temp4) {
108 | return this.normalizedToCelsius() > temp4.normalizedToCelsius();
109 | }
110 |
111 | private double normalizedToCelsius() {
112 | return this.unit == TemperatureUnit.CELSIUS ? this.value : ((this.value - 32) * 5) / 9;
113 | }
114 | }
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/concepts/Delegation_TestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.concepts;
2 |
3 | //---------------------------------------
4 | //--- STEP 00 - WHAT IS DELEGATION?
5 | //---------------------------------------
6 |
7 | ///**
8 | // * Delegation = hand over the responsibility for a particular task to another class or method.
9 | // *
10 | // * Ask for help, not for information. Don't get() the data. Ask the object that has the data to do the work for you. The object that has the information does the work.
11 | // *
12 | // * If you need to use functionality in another class but you do not want to change that functionality then use delegation instead of inheritance.
13 | // */
14 |
15 | //---------------------------------------
16 | //--- STEP 01 - UNDERSTAND DELEGATION (ALONG WITH POLYMORPHISM) BY EXAMPLE
17 | //---------------------------------------
18 |
19 | /**
20 | * This is test class for the delegation and polymorphism example
21 | *
22 | * @author tirthalp
23 | * @see Delegation_InsteadOfGetterSetter_TestDrive
24 | */
25 | public class Delegation_TestDrive {
26 |
27 | public static void main(String[] args) {
28 | // Here TicketBookingByAgent class is internally delegating train ticket booking responsibility to other class
29 | TicketBookingByAgent agent = new TicketBookingByAgent(new TrainBooking());
30 | agent.bookTicket();
31 |
32 | // Here TicketBookingByAgent class is internally delegating airline ticket booking responsibility to other class
33 | agent = new TicketBookingByAgent(new AirBooking());
34 | agent.bookTicket();
35 | }
36 | }
37 |
38 | /**
39 | * TicketBokkingByAgent provides implementation of TravelBooking. But it delegates actual ticket booking to other class at runtime using Polymorphism.
40 | *
41 | * @author tirthalp
42 | *
43 | */
44 | class TicketBookingByAgent implements TravelBooking {
45 |
46 | TravelBooking t;
47 |
48 | public TicketBookingByAgent(TravelBooking t) {
49 | this.t = t;
50 | }
51 |
52 | // Delegation --- Here ticket booking responsibility is delegated to other class using polymorphism
53 | @Override
54 | public void bookTicket() {
55 | t.bookTicket();
56 | }
57 | }
58 |
59 | /**
60 | * This represents TravelBooking interface
61 | *
62 | * @author tirthalp
63 | *
64 | */
65 | interface TravelBooking {
66 | public void bookTicket();
67 | }
68 |
69 | /**
70 | * TrainBooking IS-A TravelBooking type
71 | *
72 | * @author tirthalp
73 | *
74 | */
75 | class TrainBooking implements TravelBooking {
76 | @Override
77 | public void bookTicket() {
78 | System.out.println("Train ticket booked");
79 | }
80 | }
81 |
82 | /**
83 | * AirBooking IS-A TravelBooking type
84 | *
85 | * @author tirthalp
86 | *
87 | */
88 | class AirBooking implements TravelBooking {
89 | @Override
90 | public void bookTicket() {
91 | System.out.println("Flight ticket booked");
92 | }
93 | }
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/concepts/Encapsulation_TestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.concepts;
2 |
3 | //---------------------------------------
4 | //--- STEP 00 - WHAT IS ABSTRACTION & ENCAPSULATION?
5 | //---------------------------------------
6 |
7 | ///**
8 | // * Abstraction = Looking only at the information that is relevant at the time.
9 | // *
10 | // * Abstraction is the process or result of generalization by reducing the information content of a concept or an observable phenomenon,
11 | // * typically in order to retain only information which is relevant for a particular purpose. It is starting point of design.
12 | // * Functional abstraction - means that a function can be used without taking into account how the function is implemented.
13 | // * Data Abstraction - means that data can be used without taking into account how the data are stored.
14 | // */
15 |
16 | ///**
17 | // * Encapsulation = Data hiding mechanism.
18 | // *
19 | // * The process of binding or wrapping the data and the codes that operates on the data into a single entity. This keeps the data safe from
20 | // * outside interface and misuse. One way to think about encapsulation is as a protective wrapper that prevents code and data from being arbitrarily
21 | // * accessed by other code defined outside the wrapper.
22 | // * For example - if a field is declared private, it cannot be accessed by anyone outside the class, thereby hiding the fields within the class.
23 | // */
24 |
25 | //---------------------------------------
26 | //--- STEP 01 - UNDERSTAND ENCAPSULATION BY EXAMPLE
27 | //---------------------------------------
28 |
29 | /**
30 | *
31 | * Encapsulation goals of Person class
32 | *
33 | * (1) The id and name parameters should not be accessible directly outside Person class - achieved by private declaration
34 | *
35 | * (2) The id value can be assigned in Person class only and other class should not be able to change - not included setId() method
36 | *
37 | * @author tirthalp
38 | *
39 | */
40 | class Person {
41 |
42 | private double id;
43 | private String name;
44 |
45 | public Person() {
46 | // Only Person class can access and assign
47 | id = Math.random();
48 | sayHello();
49 | }
50 |
51 | // This method is protected for giving access within Person class only
52 | private void sayHello() {
53 | System.out.println("Hello - " + getId());
54 | }
55 |
56 | public double getId() {
57 | return id;
58 | }
59 |
60 | public String getName() {
61 | return name;
62 | }
63 | public void setName(String name) {
64 | this.name = name;
65 | }
66 | }
67 |
68 | /**
69 | * Test class for Person
70 | *
71 | * @author tirthalp
72 | *
73 | */
74 | public class Encapsulation_TestDrive {
75 |
76 | public static void main(String[] args) {
77 |
78 | Person p1 = new Person();
79 | p1.setName("Tirthal");
80 | /*
81 | * Note: As id and name are encapsulated in Person class, those cannot be accessed directly here. Also there is no way to assign id in this
82 | * class. Try to uncomment below code and you would find compile time error.
83 | */
84 | // p1.id = "123";
85 | // p1.name = "this will give compile time error";
86 | // p1.sayHello(); // You can't access this method, as it is private to Person
87 |
88 | System.out.println("Person 1 - " + p1.getId() + " : " + p1.getName());
89 | }
90 | }
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/concepts/Inheritance_TestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.concepts;
2 |
3 | //---------------------------------------
4 | //--- STEP 00 - WHAT IS INHERITANCE?
5 | //---------------------------------------
6 |
7 | ///**
8 | // * Inheritance = is-a relationship between a superclass and its subclasses.
9 | // *
10 | // * For example, Dog (subclass) is-a of type Animal (superclass). So Dog can inherit (reuse) members of Animal class;
11 | // * plus it can have its own new behavior and properties.
12 | // */
13 |
14 | //---------------------------------------
15 | //--- STEP 01 - UNDERSTAND INHERITANCE BY EXAMPLE
16 | //---------------------------------------
17 |
18 | /**
19 | * Test class for inheritance behavior - Dog class is inheriting behavior and properties of Animal class and can have its own too.
20 | *
21 | * @author tirthalp
22 | *
23 | */
24 | public class Inheritance_TestDrive {
25 |
26 | public static void main(String[] args) {
27 | Dog dog = new Dog();
28 | dog.setId(123); // inherited from super class
29 | dog.sound(); // overrided behavior of sub class
30 | }
31 | }
32 |
33 | /**
34 | * This is parent (also called as super or base) class Animal
35 | *
36 | * @author tirthalp
37 | *
38 | */
39 | class Animal {
40 | int id;
41 |
42 | public int getId() {
43 | return id;
44 | }
45 |
46 | public void setId(int id) {
47 | this.id = id;
48 | }
49 |
50 | public void sound() {
51 | System.out.println("By default it is mute");
52 | }
53 | }
54 |
55 | /**
56 | * This is subclass (also called as derived or child or extended) Dog which is extending Animal
57 | *
58 | * @author tirthalp
59 | *
60 | */
61 | class Dog extends Animal {
62 |
63 | // Own behavior
64 | private void bark() {
65 | System.out.println("Dog '" + getId() + "' is barking");
66 | }
67 |
68 | // Overriding super class behavior
69 | @Override
70 | public void sound() {
71 | bark();
72 | }
73 | }
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/concepts/LooseCoupling_TestDrive.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPrinciples/src/com/tirthal/learning/oop/concepts/LooseCoupling_TestDrive.java
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/concepts/Polymorphism_TestDrive.java:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPrinciples/src/com/tirthal/learning/oop/concepts/Polymorphism_TestDrive.java
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/concepts/README.md:
--------------------------------------------------------------------------------
1 | For more detail, please read [here](http://tirthalpatel.blogspot.in/2014/01/oop-design-part-1-fundamentals.html)
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/README.md:
--------------------------------------------------------------------------------
1 | S --- SRP = Single Responsibility Principle
2 |
3 | O --- OCP = Open Closed Principle
4 |
5 | L --- LSP = Liskov's Substitution Principle
6 |
7 | I --- ISP = Interface segregation principle
8 |
9 | D --- DIP = Dependency Inversion Principle
10 |
11 |
12 | For more detail, please read [here](http://tirthalpatel.blogspot.in/2014/04/oop-design-part-2-class-principles-solid.html)
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/dip/README.md:
--------------------------------------------------------------------------------
1 | *** DIP = Dependency Inversion Principle
2 | -----------------------------------------------
3 |
4 | *** Description =
5 |
6 | - The Dependency Inversion Principle (DIP) states that high-level modules should not depend upon low-level modules; they should depend on abstractions.
7 |
8 | - Secondly, abstractions should not depend upon details; details should depend upon abstractions. The idea is that we isolate our class behind a boundary
9 | formed by the abstractions it depends on. If all the details behind those abstractions change, then our class is still safe. This helps keep coupling
10 | low and makes our design easier to change. DIP also allows us to test things in isolation, details like database are plugins to our system.
11 |
12 | -----------------------------------------------
13 |
14 | *** Examples =
15 |
16 | (1) Authenticate (package = com.tirthal.learning.oop.design.principles.clazz.solid.dip.authentication)
17 |
18 | Requirement - Provide login by authenticating using Simple DB logic. In future, there may require adding more options such as LDAP based authentication.
19 |
20 | ------ First let's see "bad" design and implementation (package = com.tirthal.learning.oop.design.principles.clazz.solid.dip.authentication.bad)
21 |
22 | - Refer LoginManager.java and SimpleAuthenticator.java
23 |
24 | ------ How to do code-refactoring to make "good" design using DIP? (package = com.tirthal.learning.oop.design.principles.clazz.solid.dip.authentication.good)
25 |
26 | - Refer LoginManager.java
27 | - Refer SimpleAuthenticator.java and LDAPAuthenticator.java, which implements Authenticator.java interface
28 |
29 | -----------------------------------------------
30 |
31 | Feel free to contribute code for more examples in similar fashion... :-)
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/dip/authentication/bad/LoginManager.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.dip.authentication.bad;
2 |
3 | /**
4 | * High level class for login. Why DIP is violated?
5 | *
6 | * In this example, the LoginManager class is directly dependent on SimpleAuthenticator, which has no abstractions and is the implementing
7 | * class. In case of new authentication mechanism in future, LoginManager would be changed and the unit testing should be redone.
8 | *
9 | * @author tirthalp
10 | *
11 | */
12 | public class LoginManager {
13 |
14 | SimpleAuthenticator simpleAuthenticator = new SimpleAuthenticator();
15 |
16 | public void login(User user) {
17 | simpleAuthenticator.authenticate(user);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/dip/authentication/bad/SimpleAuthenticator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.dip.authentication.bad;
2 |
3 | /**
4 | *
5 | * Low level class of authentication
6 | *
7 | * @author tirthalp
8 | *
9 | */
10 | public class SimpleAuthenticator {
11 |
12 | public boolean authenticate(User user) {
13 |
14 | // logic - database
15 |
16 | return true;
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/dip/authentication/bad/User.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.dip.authentication.bad;
2 |
3 | public class User {
4 |
5 | private int id;
6 |
7 | public int getId() {
8 | return id;
9 | }
10 |
11 | public void setId(int id) {
12 | this.id = id;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/dip/authentication/good/Authenticator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.dip.authentication.good;
2 |
3 | /**
4 | * The example low level interface to provide abstraction
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public interface Authenticator {
10 |
11 | boolean authenticate(User user);
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/dip/authentication/good/LDAPAuthenticator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.dip.authentication.good;
2 |
3 | /**
4 | * The example low level class, which would provide implementation of authentication by LDAP
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class LDAPAuthenticator implements Authenticator {
10 |
11 | @Override
12 | public boolean authenticate(User user) {
13 | // logic - LDAP
14 | return true;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/dip/authentication/good/LoginManager.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.dip.authentication.good;
2 |
3 | /**
4 | * High level class for login, which follows DIP.
5 | *
6 | * In this example, the LoginManager class is not directly dependent on SimpleAuthenticator or LDAPAuthenticator implementation class. Rather it depends
7 | * on Authenticator interface which provides abstractions.
8 | *
9 | * In case of adding new authentication mechanism in future, LoginManager and its unit test would not be changed.
10 | *
11 | * @author tirthalp
12 | *
13 | */
14 | public class LoginManager {
15 |
16 | Authenticator authenticator;
17 |
18 | public void setAuthenticator(Authenticator authenticator) {
19 | this.authenticator = authenticator;
20 | }
21 |
22 | public void login(User user) {
23 | authenticator.authenticate(user);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/dip/authentication/good/SimpleAuthenticator.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.dip.authentication.good;
2 |
3 | /**
4 | * The example low level class, which would provide implementation of authentication by database
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class SimpleAuthenticator implements Authenticator {
10 |
11 | @Override
12 | public boolean authenticate(User user) {
13 | // logic - database
14 | return true;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/dip/authentication/good/User.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.dip.authentication.good;
2 |
3 | public class User {
4 |
5 | private int id;
6 |
7 | public int getId() {
8 | return id;
9 | }
10 |
11 | public void setId(int id) {
12 | this.id = id;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/isp/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/isp/README.md
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/isp/order/bad/Order.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.isp.order.bad;
2 |
3 | /**
4 | * The sample order POJO / Entity
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Order {
10 |
11 | private int id;
12 |
13 | public int getId() {
14 | return id;
15 | }
16 |
17 | public void setId(int id) {
18 | this.id = id;
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/isp/order/bad/OrderService.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.isp.order.bad;
2 |
3 | /**
4 | * Why ISP is violated here in the order service design? Because,
5 | *
6 | * User client - Forced to depend on process order unnecessarily.
7 | *
8 | * Backend job client - only need process order, but still forced to depend on other services too.
9 | *
10 | * Note - To keep example in simplest form, I didn't consider exact low-level API design of the mentioned methods.
11 | *
12 | * @author tirthalp
13 | */
14 | public interface OrderService {
15 |
16 | // ------------ Order services consumed by the user client
17 |
18 | /**
19 | * Create order
20 | *
21 | * @return new created order instance having unique id
22 | */
23 | public Order createOrder();
24 |
25 | /**
26 | * Change order
27 | *
28 | * @return updated order instance
29 | */
30 | public Order amendOrder();
31 |
32 | /**
33 | * Cancel order
34 | *
35 | * @param orderId
36 | *
37 | * @return status of order cancellation operation
38 | */
39 | public boolean cancelOrder(int orderId);
40 |
41 | /**
42 | * Submit order
43 | *
44 | * @param orderId
45 | * @return submitted order instance
46 | */
47 | public Order submitOrder(int orderId);
48 |
49 | /**
50 | * Get order detail by order id
51 | *
52 | * @param orderId
53 | * @return order instance for given orderId
54 | */
55 | public Order getOrder(int orderId);
56 |
57 | // ------------ Order services consumed by the backend/integration job client
58 |
59 | /**
60 | * This is responsible for processing the order for delivery
61 | *
62 | * @return status of the order processed by job
63 | */
64 | public boolean processOrder(int orderId);
65 | }
66 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/isp/order/good/Order.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.isp.order.good;
2 |
3 | /**
4 | * The sample order POJO / Entity
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Order {
10 |
11 | private int id;
12 |
13 | public int getId() {
14 | return id;
15 | }
16 |
17 | public void setId(int id) {
18 | this.id = id;
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/isp/order/good/OrderProcessingService.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.isp.order.good;
2 |
3 | /**
4 | * After refactoring, all services apart from processOrder() are kept in another interface. So now backend job client is not forced to depend on
5 | * those unnecessary OrderService(s).
6 | *
7 | * Note - To keep example in simplest form, I didn't consider exact low-level API design of the mentioned methods.
8 | *
9 | * @author tirthalp
10 | */
11 | public interface OrderProcessingService {
12 |
13 | // ------------ Order services consumed by the backend/integration job client
14 |
15 | /**
16 | * This is responsible for processing the order for delivery
17 | *
18 | * @return status of the order processed by job
19 | */
20 | public boolean processOrder(int orderId);
21 | }
22 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/isp/order/good/OrderService.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.isp.order.good;
2 |
3 | /**
4 | * After refactoring, processOrder() is moved in another interface. So now user client is not forced to depend on it unnecessarily.
5 | * Also vice-versa is true, as backend job client is not forced to depend on OrderService.
6 | *
7 | * Note - To keep example in simplest form, I didn't consider exact low-level API design of the mentioned methods.
8 | *
9 | * @author tirthalp
10 | */
11 | public interface OrderService {
12 |
13 | // ------------ Order services consumed by the user client
14 |
15 | /**
16 | * Create order
17 | *
18 | * @return new created order instance having unique id
19 | */
20 | public Order createOrder();
21 |
22 | /**
23 | * Change order
24 | *
25 | * @return updated order instance
26 | */
27 | public Order amendOrder();
28 |
29 | /**
30 | * Cancel order
31 | *
32 | * @param orderId
33 | *
34 | * @return status of order cancellation operation
35 | */
36 | public boolean cancelOrder(int orderId);
37 |
38 | /**
39 | * Submit order
40 | *
41 | * @param orderId
42 | * @return submitted order instance
43 | */
44 | public Order submitOrder(int orderId);
45 |
46 | /**
47 | * Get order detail by order id
48 | *
49 | * @param orderId
50 | * @return order instance for given orderId
51 | */
52 | public Order getOrder(int orderId);
53 | }
54 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthalpatel/Learning-OOPD/4a591474a87912f1c8395083cec3dff02a0da6c5/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/README.md
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/bad/ClientTestProgram.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.bad;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * This is sample client program which refers MediaPlayer
8 | *
9 | * @author tirthalp
10 | */
11 | public class ClientTestProgram {
12 |
13 | public static void main(String[] args) {
14 |
15 | // Created list of players
16 | List allPlayers = new ArrayList();
17 | allPlayers.add(new VlcMediaPlayer());
18 | allPlayers.add(new DivMediaPlayer());
19 |
20 | // Play video in all players
21 | playVideoInAllMediaPlayers(allPlayers);
22 |
23 | // Well - all works as of now...... :-)
24 | System.out.println("---------------------------");
25 |
26 | // Now adding new Winamp player
27 | allPlayers.add(new WinampMediaPlayer());
28 |
29 | // Again play video in all players & Oops it broke the program... :-(
30 | // Why we got unexpected behavior in client? --- Because LSP is violated in WinampMediaPlayer.java, as it changed the original behavior of super class MediaPlayer.java
31 | playVideoInAllMediaPlayers(allPlayers);
32 | }
33 |
34 | /**
35 | * This method is playing video in all players
36 | *
37 | * @param allPlayers
38 | */
39 | public static void playVideoInAllMediaPlayers(List allPlayers) {
40 |
41 | for(MediaPlayer player : allPlayers) {
42 | player.playVideo();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/bad/DivMediaPlayer.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.bad;
2 |
3 | /**
4 | * Div Media player extending behavior of super class Media player. Perfect, LSP is not violated here.
5 | *
6 | * @author tirthalp
7 | */
8 | public class DivMediaPlayer extends MediaPlayer {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/bad/MediaPlayer.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.bad;
2 |
3 | /**
4 | * Example media player super class which has ability to play video and audio
5 | *
6 | * @author tirthalp
7 | */
8 | public class MediaPlayer {
9 |
10 | // Play audio implementation
11 | public void playAudio() {
12 | System.out.println("Playing audio...");
13 | }
14 |
15 | // Play video implementation
16 | public void playVideo() {
17 | System.out.println("Playing video...");
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/bad/VideoUnsupportedException.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.bad;
2 |
3 | public class VideoUnsupportedException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = 1L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/bad/VlcMediaPlayer.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.bad;
2 |
3 | /**
4 | * VLC Media player extending behavior of super class Media player. Perfect, LSP is not violated here.
5 | *
6 | * @author tirthalp
7 | */
8 | public class VlcMediaPlayer extends MediaPlayer {
9 |
10 | }
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/bad/WinampMediaPlayer.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.bad;
2 |
3 | /**
4 | * Now there is a need of launching new Winamp player to play audio, but playing video is not supported at this stage.
5 | *
6 | * Oops... LSP is violated here! Why? Logically winamp player only supports playing audio. So what's wrong in overriding playVideo method of super class?
7 | *
8 | * Well, see how it broke the client program (ClientTestProgram.java)
9 | *
10 | * @author tirthalp
11 | */
12 | public class WinampMediaPlayer extends MediaPlayer {
13 |
14 | // Play video is not supported in Winamp player
15 | public void playVideo() {
16 | throw new VideoUnsupportedException();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/good/AudioMediaPlayer.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.good;
2 |
3 | /**
4 | * This class is getting ability of playing audio from its super class
5 | *
6 | * @author tirthalp
7 | */
8 | public class AudioMediaPlayer extends MediaPlayer {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/good/ClientTestProgram.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.good;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * This is sample client program which refers MediaPlayer
8 | *
9 | * @author tirthalp
10 | */
11 | public class ClientTestProgram {
12 |
13 | public static void main(String[] args) {
14 |
15 | // Created list of video players
16 | List allPlayers = new ArrayList();
17 | allPlayers.add(new VlcMediaPlayer());
18 | allPlayers.add(new DivMediaPlayer());
19 |
20 | // Play video in all players
21 | playVideoInAllMediaPlayers(allPlayers);
22 |
23 | // Well - all works as of now...... :-)
24 | System.out.println("---------------------------");
25 |
26 | // Now adding new Winamp player. If you uncomment below line, it would give compile time error as can't add audio player in list of video players.
27 | // allPlayers.add(new WinampMediaPlayer());
28 | }
29 |
30 | /**
31 | * This method is playing video in all players
32 | *
33 | * @param allPlayers
34 | */
35 | public static void playVideoInAllMediaPlayers(List allPlayers) {
36 |
37 | for(VideoMediaPlayer player : allPlayers) {
38 | player.playVideo();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/good/DivMediaPlayer.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.good;
2 |
3 | /**
4 | * Div Media player extending behavior of super class Video Media Player. Perfect, LSP is not violated here.
5 | *
6 | * @author tirthalp
7 | */
8 | public class DivMediaPlayer extends VideoMediaPlayer {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/good/MediaPlayer.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.good;
2 |
3 | /**
4 | * Example media player super class which has ability to play audio
5 | *
6 | * @author tirthalp
7 | */
8 | public class MediaPlayer {
9 |
10 | // Play audio implementation
11 | public void playAudio() {
12 | System.out.println("Playing audio...");
13 | }
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/good/VideoMediaPlayer.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.good;
2 |
3 | /**
4 | * This class has ability to play video as well as getting audio ability from super class
5 | *
6 | * @author tirthalp
7 | */
8 | public class VideoMediaPlayer extends MediaPlayer {
9 |
10 | // Play video implementation
11 | public void playVideo() {
12 | System.out.println("Playing video...");
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/good/VideoUnsupportedException.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.good;
2 |
3 | public class VideoUnsupportedException extends RuntimeException {
4 |
5 | private static final long serialVersionUID = 1L;
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/good/VlcMediaPlayer.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.good;
2 |
3 | /**
4 | * VLC Media player extending behavior of super class Video Media Player. Perfect, LSP is not violated here.
5 | *
6 | * @author tirthalp
7 | */
8 | public class VlcMediaPlayer extends VideoMediaPlayer {
9 |
10 | }
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/lsp/mediaplayer/good/WinampMediaPlayer.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.lsp.mediaplayer.good;
2 |
3 | /**
4 | * Now there is a need of launching new Winamp player to play audio, but playing video is not supported at this stage.
5 | *
6 | * So Winamp Media player extending behavior of super class Audio Media Player. Perfect, LSP is not violated here.
7 | *
8 | * @author tirthalp
9 | */
10 | public class WinampMediaPlayer extends AudioMediaPlayer {
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/README.md:
--------------------------------------------------------------------------------
1 | *** OCP = Open Closed Principle
2 | -----------------------------------------------
3 |
4 | *** Description = http://www.oodesign.com/design-principles.html
5 |
6 | - "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification"; that is, such an entity can allow its behaviour to be extended without modifying its source code.
7 |
8 | - If you have a library containing a set of classes there are many reasons for which you'll prefer to extend it without changing the code
9 | that was already written (backward compatibility, regression testing...). This is why we have to make sure our modules follow Open Closed Principle.
10 |
11 | - When referring to the classes Open Close Principle can be ensured by use of Abstract classes and Concrete classes for implementing their behavior.
12 | This will enforce having Concrete Classes extending Abstract Classes instead of changing them.
13 | Some particular cases of this are Template Pattern and Strategy Pattern.
14 |
15 |
16 | -----------------------------------------------
17 |
18 | *** Examples =
19 |
20 | (1) File Parser (package = com.tirthal.learning.oop.design.principles.clazz.solid.ocp.parsing)
21 |
22 | Requirement - Need to develop file parsing for XML and TXT types.
23 |
24 | ------ First let's see "bad" design and implementation
25 |
26 | - Refer com.tirthal.learning.oop.design.principles.clazz.solid.ocp.parsing.bad.FileParser
27 | - parse() contains if-else conditional logic to parse the file based on type
28 | - In future if you need to extend it to support CSV type, then what will you do? Well you have to change parse() to add one more condition. So OCP is violated.
29 |
30 | ------ How to do code-refactoring to make "good" design using OCP?
31 |
32 | - Refer com.tirthal.learning.oop.design.principles.clazz.solid.ocp.parsing.good.FileParser
33 | - FileParser is abstract class. Now to support new type of parsing support, just implement new class extending FileParser class.
34 | - So OCP is followed, because there is no modification in FileParser to extend new type.
35 |
36 | (2) Order Import and Export (package = com.tirthal.learning.oop.design.principles.clazz.solid.ocp.exporter)
37 |
38 | Requirement - Need to support order export in JSON and XML formats.
39 |
40 | ------ First let's see "bad" design and implementation
41 |
42 | - Refer com.tirthal.learning.oop.design.principles.clazz.solid.ocp.exporter.bad.Order
43 | - See exportAsJson() and exportAsXml()
44 | - In future if you need to extend it to support SQL export, then what will you do? Well you have to modify Order class to add exportAsSql() for SQL format. So OCP is violated.
45 |
46 | ------ How to do code-refactoring to make "good" design using OCP?
47 |
48 | - Refer com.tirthal.learning.oop.design.principles.clazz.solid.ocp.exporter.good.Order
49 | - See usage of Importer and Exporter interfaces in Order class
50 | - In future if you need to extend it to support SQL export, then what will you do? Well, just implement new SqlImporter and SqlExporter classes.
51 | - So OCP is followed, because there is no modification in Order class to extend SQL export support.
52 |
53 | (3) Drawing Shapes (package = com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing)
54 |
55 | - Reference: http://www.oodesign.com/open-close-principle.html
56 |
57 | ------- Bad design - OCP is violated (Refer GraphicEditor)
58 |
59 | - package = com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.bad
60 |
61 | ------- Good design - OCP is followed
62 |
63 | - package = com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.good
64 |
65 | -----------------------------------------------
66 |
67 | Feel free to contribute code for more examples in similar fashion... :-)
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/drawing/bad/Circle.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.bad;
2 |
3 | /**
4 | * This class indicates circle shape
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Circle extends Shape {
10 | Circle() {
11 | super.m_type = 2;
12 | }
13 | }
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/drawing/bad/GraphicEditor.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.bad;
2 |
3 | /**
4 | * Well, we can see here OCP is violated.
5 | *
6 | * Because if we need to extend it to support drawing square, then it requires to change drawShape() and add new drawSquare() method in this class
7 | *
8 | * @author tirthalp
9 | *
10 | */
11 | public class GraphicEditor {
12 |
13 | /*
14 | * Draw shape as per supplied shape type
15 | */
16 | public void drawShape(Shape s) {
17 | // If it is rectangle type, then draw rectangle
18 | if (s.m_type == 1)
19 | drawRectangle((Rectangle) s);
20 | // If it is circle type, then draw circle
21 | else if (s.m_type == 2)
22 | drawCircle((Circle) s);
23 | // Add more conditions to extend drawing other types of shapes...
24 | // Difficult to maintain numeric numbers for assigned shape types and more required testing efforts as it grows
25 | }
26 |
27 | /*
28 | * Draw circle
29 | */
30 | private void drawCircle(Circle r) {
31 | System.out.println("Drawing Circle");
32 | }
33 |
34 | /*
35 | * Draw rectangle
36 | */
37 | private void drawRectangle(Rectangle r) {
38 | System.out.println("Drawing Rectangle");
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/drawing/bad/GraphicEditorTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.bad;
2 |
3 | /**
4 | * Implementation of drawing editor
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class GraphicEditorTestDrive {
10 |
11 | public static void main(String[] args) {
12 | GraphicEditor ge = new GraphicEditor();
13 |
14 | Shape s = new Rectangle();
15 | ge.drawShape(s);
16 |
17 | s = new Circle();
18 | ge.drawShape(s);
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/drawing/bad/Rectangle.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.bad;
2 |
3 | /**
4 | * This class indicates rectangle shape
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Rectangle extends Shape {
10 | Rectangle() {
11 | super.m_type = 1;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/drawing/bad/Shape.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.bad;
2 |
3 | /**
4 | * This class indicates shape type
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Shape {
10 | int m_type;
11 | }
12 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/drawing/good/Circle.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.good;
2 |
3 | /**
4 | * Implementation of drawing circle
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Circle extends Shape {
10 | public void draw() {
11 | System.out.println("Drawing circle");
12 | }
13 | }
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/drawing/good/GraphicEditor.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.good;
2 |
3 | /**
4 | * OCP is followed, as to extend functionality this class does not require to change
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class GraphicEditor {
10 |
11 | public void drawShape(Shape s) {
12 | s.draw();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/drawing/good/GraphicEditorTestDrive.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.good;
2 |
3 | /**
4 | * Implementation of drawing editor
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class GraphicEditorTestDrive {
10 |
11 | public static void main(String[] args) {
12 | GraphicEditor ge = new GraphicEditor();
13 |
14 | Shape s = new Rectangle();
15 | ge.drawShape(s);
16 |
17 | s = new Circle();
18 | ge.drawShape(s);
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/drawing/good/Rectangle.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.good;
2 |
3 | /**
4 | * Implementation of drawing rectangle
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public class Rectangle extends Shape {
10 | public void draw() {
11 | System.out.println("Drawing Rectangle");
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/drawing/good/Shape.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.drawing.good;
2 |
3 | /**
4 | * Shape class which defines draw method specification without implementation
5 | *
6 | * @author tirthalp
7 | *
8 | */
9 | public abstract class Shape {
10 | abstract void draw();
11 | }
12 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/exporter/bad/Order.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.exporter.bad;
2 |
3 | import java.io.Writer;
4 |
5 | /**
6 | * Demo of how OCP is violated? Because to support SQL export, this class needs modification.
7 | *
8 | * @author tirthalp
9 | */
10 | public class Order {
11 |
12 | @SuppressWarnings("unused")
13 | private int id;
14 | // + other order attributes
15 |
16 | public Order(int id) {
17 | this.id = id;
18 | }
19 |
20 | public Order(String source, Format inputFormat) {
21 | // ... logic implementation
22 | }
23 |
24 | public enum Format { JSON, XML }; // Add new formats in future
25 |
26 | public void exportAsJson(Writer out) {
27 | // ... logic implementation
28 | }
29 |
30 | public void exportAsXml(Writer out) {
31 | // ... logic implementation
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/exporter/good/JsonExporter.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.exporter.good;
2 |
3 | public class JsonExporter implements Order.Exporter {
4 |
5 | private Order order;
6 |
7 | @Override
8 | public void storeOrder(Order order) {
9 | this.order = order;
10 |
11 | // ... logic implementation
12 | }
13 |
14 | @Override
15 | public String toString() {
16 | return "{ \"order.id\":\"" + order.getId() + "\"";
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/exporter/good/JsonImporter.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.exporter.good;
2 |
3 | import java.io.Reader;
4 |
5 | public class JsonImporter implements Order.Importer {
6 |
7 | @SuppressWarnings("unused")
8 | private Reader in;
9 |
10 | public JsonImporter(Reader in) {
11 | this.in = in;
12 | }
13 |
14 | @Override
15 | public Order fetchOrderById(int id) {
16 |
17 | // ... logic implementation
18 |
19 | return new Order(123);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/exporter/good/Order.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.exporter.good;
2 |
3 | /**
4 | * Demo of how OCP is followed, because class can be extended for new export types, such as SQL export support, without
5 | * modifying this class
6 | *
7 | * @author tirthalp
8 | */
9 | public class Order {
10 |
11 | interface Importer {
12 | Order fetchOrderById(int id);
13 | }
14 |
15 | interface Exporter {
16 | void storeOrder(Order order);
17 | }
18 |
19 | public Order(int id) {
20 | this.id = id;
21 | }
22 |
23 | public Order(Importer source) {
24 | Order o = source.fetchOrderById(id);
25 | this.id = o.id;
26 | }
27 |
28 | public void export(Exporter destination) {
29 | destination.storeOrder(this);
30 | }
31 |
32 | public int getId() {
33 | return id;
34 | }
35 |
36 | private int id;
37 | // + other order attributes
38 | }
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/exporter/good/XmlExporter.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.exporter.good;
2 |
3 | public class XmlExporter implements Order.Exporter {
4 |
5 | private Order order;
6 |
7 | @Override
8 | public void storeOrder(Order order) {
9 | this.order = order;
10 |
11 | // ... logic implementation
12 | }
13 |
14 | @Override
15 | public String toString() {
16 | return "" + order.getId() + "";
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/exporter/good/XmlImporter.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.exporter.good;
2 |
3 | import java.io.Reader;
4 |
5 | public class XmlImporter implements Order.Importer {
6 |
7 | @SuppressWarnings("unused")
8 | private Reader in;
9 |
10 | public XmlImporter(Reader in) {
11 | this.in = in;
12 | }
13 |
14 | @Override
15 | public Order fetchOrderById(int id) {
16 |
17 | // ... logic implementation
18 |
19 | return new Order(123);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/parsing/bad/FileParser.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.parsing.bad;
2 |
3 | /**
4 | * Example file parser implementation. What's wrong?
5 | *
6 | * Well, OCP principle is violated. Why?
7 | *
8 | * In future, if there is a need to extend it for CSV Parsing, then you need to implement new method parseCSV() and change parse() to add conditional
9 | * logic. That means, more efforts to spend on code review and testing.
10 | *
11 | * @author tirthalp
12 | *
13 | */
14 | public class FileParser {
15 |
16 | private String filePath;
17 | private String expression;
18 |
19 | public FileParser(String filePath, String expression) {
20 | this.filePath = filePath;
21 | this.expression = expression;
22 | }
23 |
24 | /**
25 | * apply parsing rule based the file based on extension type
26 | *
27 | * @param filePath
28 | * @param expression
29 | * @return
30 | */
31 | public String parse() {
32 |
33 | if (filePath.indexOf(".xml") > 1) { // XML parsing condition
34 |
35 | return parseXML(filePath, expression);
36 |
37 | } else if (filePath.indexOf(".txt") > 1) { // TXT parsing condition
38 |
39 | return parseText(filePath, expression);
40 |
41 | } // ------- Add further conditional logic, if needs to support more type such as CSV parsing
42 | return null;
43 | }
44 |
45 | private String parseXML(String filePath, String expression) {
46 | // TODO: implement xml parsing logic using xpath
47 | return "this is parsing output of xml file";
48 | }
49 |
50 | private String parseText(String filePath, String expression) {
51 | // TODO: implement text parsing logic using regular expression
52 | return "this is parsing output of text file";
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/ocp/parsing/good/FileParser.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.ocp.parsing.good;
2 |
3 | // NOTE - For simplicity I kept all classes in same file, but you can have separate file for each class
4 |
5 | /**
6 | * Abstract class to define parse() specification, which follows OCP. Why?
7 | *
8 | * Well if you need to extend support for more types like CSV, then you don't need to change existing class/method. Just add new class called
9 | * CsvParser extending FileParser. That means, you just need code review and testing of new CsvParser class. This is the beauty of OCP.
10 | *
11 | * @author tirthalp
12 | *
13 | */
14 | abstract class FileParser {
15 |
16 | String filePath;
17 | String expression;
18 |
19 | public FileParser(String filePath, String expression) {
20 | this.filePath = filePath;
21 | this.expression = expression;
22 | }
23 |
24 | abstract String parse();
25 | }
26 |
27 | /**
28 | * Implementation class for XML Parser
29 | *
30 | * @author tirthalp
31 | *
32 | */
33 | class XMLParser extends FileParser {
34 |
35 | public XMLParser(String filePath, String expression) {
36 | super(filePath, expression);
37 | }
38 |
39 | @Override
40 | String parse() {
41 | // TODO: implement xml parsing logic using xpath
42 | return "";
43 | }
44 | }
45 |
46 | /**
47 | * Implementation class for TXT Parser
48 | *
49 | * @author tirthalp
50 | *
51 | */
52 | class TextParser extends FileParser {
53 |
54 | public TextParser(String filePath, String expression) {
55 | super(filePath, expression);
56 | }
57 |
58 | @Override
59 | String parse() {
60 | // TODO: implement text parsing logic using regular expression
61 | return "";
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/README.md:
--------------------------------------------------------------------------------
1 | *** SRP = Single Responsibility Principle
2 | -----------------------------------------------
3 |
4 | *** Description =
5 |
6 | - There should never be more than one reason for a class to change. In this context a responsibility is considered to be one reason to change a class.
7 |
8 | - This principle states that if we have 2 reasons to change for a class, we have to split the functionality in two classes.
9 | Each class will handle only one responsibility and in future if we need to make one change we are going to make it in the class which handle it.
10 |
11 | - When we need to make a change in a class having more responsibilities the change might affect the other functionality of the classes.
12 | When a class has more than one responsibility, there are also more triggers and reasons to change that class.
13 |
14 | - In short if we go ahead and introduce any change to given class then the change should only be limited to that class.
15 | None of the dependent classes or consumers should have to be modified to adjust to this change.
16 |
17 | -----------------------------------------------
18 |
19 | *** Examples =
20 |
21 |
22 | (1) Design of Modem (package = com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem)
23 |
24 | ------ First understand what can be "bad" design of Modem (why SRP is violated)?
25 |
26 | Package = com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad
27 |
28 | Problems =
29 | (1) IModem doesn't indicate clearly its responsibilities (sign of bad smell)
30 | (2) Single IModem has two responsibilities - connection management + data management. That means, it has more than one reasons to change.
31 | (3) Difficult to understand and maintain as it grows.
32 |
33 | Are you still wondering, what's problem in that??? Let's understand by code example,
34 |
35 | (1) First develop "SLOW" modem and understand code as below.
36 | - Refer IModem interface (violating SRP)
37 | - Refer ModemSlow class implements IModem interface (violating SRP)
38 | - Refer ModemSlowClient class which is consumer of ModemSlow class
39 |
40 | (2) Now understand impact, if there is a need to add "FAST" modem type.
41 | - Refer ModemFast class implements IModem interface (violating SRP)
42 | - Refer ModemFastClient class which is consumer of ModemFast class
43 |
44 | PROBLEM IS,
45 |
46 | - The connection management responsibility (dial and disconnected) is duplicated in both ModemSlow and ModemFast classes
47 | - Also in future if modem requires to dial with password logic, then it would require to change both ModemFast and ModemSlow.
48 |
49 | (3) Now just think, how can you add "SUPER FAST" modem in similar way and how more complexity will increase?
50 |
51 |
52 | ------ Now follow SRP (along with delegation principle) for "good" design of Modem:
53 |
54 | Package = com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.good
55 |
56 | Solution =
57 |
58 | (1) Follow SRP - IConnection interface is responsible for connection management. IDataChannel interface is responsible for data exchange.
59 |
60 | (2) Each interface or corresponding class is focused to single responsibility.
61 | - class ConnectionManager implements IConnection (for connection management responsibilities)
62 | - class DataChannelSlowMode implements IDataChannel (for data exchange using "SLOW" modem type)
63 |
64 | (3) Model class - implemented using Delegation design principle.
65 |
66 | (4) How does it give better control for incorporating future changes or maintenance?
67 | - Let's see how to add "FAST" modem type? We'll, just add class DataChannelFastMode which implements IDataChannel.
68 | - Also in future if modem requires to dial with password logic, then it just requires to change logic in dial() of ConnectionManager class. No impact in other classes.
69 |
70 | (5) Now just think, how can you add "SUPER FAST" type of modem in similar way?
71 |
72 |
73 |
74 |
75 | (2) Sample code is not implemented yet for below example requirement. You can try, if you really understood SRP!
76 |
77 | - Download file from given path
78 | - Apply parsing rules on given file
79 | - Store parsing output
80 |
81 | Thoughts:
82 |
83 | - Bad design by violating SRP:
84 | - Put all responsibilities in single interface and class
85 | - For example,
86 | - IDataProcessing.java (interface), FileProcessor.java (class implements IDataProcessing.java)
87 |
88 | - Better design by following SRP:
89 | - Each interface/class to focus on single responsibility and the name is enough to express its single responsibility
90 | - For example,
91 | - IDownloader.java (interface), FileDownloader.java (class implements IDownloader.java)
92 | - IParser.java (interface), CsvFileParser.java (class implements IParser.java), may be in future there can be XmlFileParser.java (class implements IParser.java)
93 | - IDataStore.java (interface), DatabaseStore (class implements IDataStore.java)
94 |
95 | -----------------------------------------------
96 |
97 | Feel free to contribute code for more examples in similar fashion... :-)
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/bad/IModem.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad;
5 |
6 | /**
7 | * Design of ModemSlow interface.
8 | *
9 | * Why is it bad design? What's the problem?
10 | *
11 | * It has two responsibilities - Connection management + Data Management. Hence SRP is violated.
12 | *
13 | * @author tirthalp
14 | */
15 | public interface IModem {
16 |
17 | // --- Connection management responsibilities = dial, disconnect
18 |
19 | public void dial(String phoneNumber);
20 |
21 | public void disconnect();
22 |
23 | // --- Data management responsibilities = send, receive
24 |
25 | public void send(char c);
26 |
27 | public char receive();
28 | }
29 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/bad/ModemFast.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad;
5 |
6 | /**
7 | * Implementation class of modem interface for "fast mode" of data send and receive. This is for design demo, so actual logic is not implemented
8 | *
9 | * @author tirthalp
10 | */
11 | public class ModemFast implements IModem {
12 |
13 | /*
14 | * (non-Javadoc)
15 | *
16 | * @see com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad.IModem#dial(java.lang.String)
17 | */
18 | @Override
19 | public void dial(String phoneNumber) {
20 | // TODO Auto-generated method stub
21 | System.out.println("connected successfully");
22 | }
23 |
24 | /*
25 | * (non-Javadoc)
26 | *
27 | * @see com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad.IModem#disconnect()
28 | */
29 | @Override
30 | public void disconnect() {
31 | // TODO Auto-generated method stub
32 | System.out.println("disconnection successfully");
33 | }
34 |
35 | /*
36 | * (non-Javadoc)
37 | *
38 | * @see com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad.IModem#send(char)
39 | */
40 | @Override
41 | public void send(char c) {
42 | // TODO Auto-generated method stub
43 | System.out.println("data sent successfully usign fast algorithms");
44 | }
45 |
46 | /*
47 | * (non-Javadoc)
48 | *
49 | * @see com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad.IModem#receive()
50 | */
51 | @Override
52 | public char receive() {
53 | // TODO Auto-generated method stub
54 | System.out.println("data received successfully using fast algorithms");
55 | return 0;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/bad/ModemFastClient.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad;
2 |
3 | /**
4 | * This is client or consumer of ModemFast class.
5 | *
6 | * @author tirthalp
7 | */
8 | public class ModemFastClient {
9 |
10 | public static void main(String[] args) {
11 |
12 | IModem fastModem = new ModemFast();
13 |
14 | fastModem.dial("0000000000");
15 | fastModem.send('t');
16 | fastModem.receive();
17 | fastModem.disconnect();
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/bad/ModemSlow.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad;
5 |
6 | /**
7 | * Implementation class of modem interface for "slow mode" of data send and receive. This is for design demo, so actual logic is not implemented
8 | *
9 | * @author tirthalp
10 | */
11 | public class ModemSlow implements IModem {
12 |
13 | /*
14 | * (non-Javadoc)
15 | *
16 | * @see com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad.IModem#dial(java.lang.String)
17 | */
18 | @Override
19 | public void dial(String phoneNumber) {
20 | // TODO Auto-generated method stub
21 | System.out.println("connected successfully");
22 | }
23 |
24 | /*
25 | * (non-Javadoc)
26 | *
27 | * @see com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad.IModem#disconnect()
28 | */
29 | @Override
30 | public void disconnect() {
31 | // TODO Auto-generated method stub
32 | System.out.println("disconnection successfully");
33 | }
34 |
35 | /*
36 | * (non-Javadoc)
37 | *
38 | * @see com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad.IModem#send(char)
39 | */
40 | @Override
41 | public void send(char c) {
42 | // TODO Auto-generated method stub
43 | System.out.println("data sent successfully usign slow algorithms");
44 | }
45 |
46 | /*
47 | * (non-Javadoc)
48 | *
49 | * @see com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad.IModem#receive()
50 | */
51 | @Override
52 | public char receive() {
53 | // TODO Auto-generated method stub
54 | System.out.println("data received successfully using slow algorithms");
55 | return 0;
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/bad/ModemSlowClient.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.bad;
2 |
3 | /**
4 | * This is client or consumer of ModemSlow class.
5 | *
6 | * @author tirthalp
7 | */
8 | public class ModemSlowClient {
9 |
10 | public static void main(String[] args) {
11 |
12 | IModem slowModem = new ModemSlow();
13 |
14 | slowModem.dial("0000000000");
15 | slowModem.send('t');
16 | slowModem.receive();
17 | slowModem.disconnect();
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/good/ConnectionManager.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.good;
5 |
6 | /**
7 | * Implementation class of IConnection interface for modem's connection management. This is for design demo, so actual logic is not implemented
8 | *
9 | * @author tirthalp
10 | *
11 | */
12 | public class ConnectionManager implements IConnection {
13 |
14 | /*
15 | * (non-Javadoc)
16 | *
17 | * @see com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.good.IConnection#dial(java.lang.String)
18 | */
19 | @Override
20 | public void dial(String phoneNumber) {
21 | // TODO Auto-generated method stub
22 | System.out.println("connected successfully");
23 | }
24 |
25 | /*
26 | * (non-Javadoc)
27 | *
28 | * @see com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.good.IConnection#disconnect()
29 | */
30 | @Override
31 | public void disconnect() {
32 | // TODO Auto-generated method stub
33 | System.out.println("disconnection successfully");
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/good/DataChannelFastMode.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.good;
2 |
3 | /**
4 | * Implementation class of IDataChannel interface for "fast mode" of data send and receive. This is for design demo, so actual logic is not
5 | * implemented
6 | *
7 | * @author tirthalp
8 | *
9 | */
10 | public class DataChannelFastMode implements IDataChannel {
11 |
12 | @Override
13 | public void send(char c) {
14 | // TODO Auto-generated method stub
15 | System.out.println("sent data using fast algorithm");
16 | }
17 |
18 | @Override
19 | public char receive() {
20 | // TODO Auto-generated method stub
21 | System.out.println("received data using fast algorithm");
22 | return 0;
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/good/DataChannelSlowMode.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.good;
2 |
3 | /**
4 | * Implementation class of IDataChannel interface for "slow mode" of data send and receive. This is for design demo, so actual logic is not
5 | * implemented
6 | *
7 | * @author tirthalp
8 | *
9 | */
10 | public class DataChannelSlowMode implements IDataChannel {
11 |
12 | @Override
13 | public void send(char c) {
14 | // TODO Auto-generated method stub
15 | System.out.println("sent data using slow algorithm");
16 | }
17 |
18 | @Override
19 | public char receive() {
20 | // TODO Auto-generated method stub
21 | System.out.println("recieved data using slow algorithm");
22 | return 0;
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/good/IConnection.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.good;
5 |
6 | /**
7 | * Interface designed for connection management responsibilities of modem
8 | *
9 | * @author tirthalp
10 | *
11 | */
12 | public interface IConnection {
13 |
14 | public void dial(String phoneNumber);
15 |
16 | public void disconnect();
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/good/IDataChannel.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.good;
5 |
6 | /**
7 | * Interface designed for data management responsibilities of modem
8 | *
9 | * @author tirthalp
10 | *
11 | */
12 | public interface IDataChannel {
13 |
14 | public void send(char c);
15 |
16 | public char receive();
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/good/Modem.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.good;
2 |
3 | //If you don't know what is delegation principle, then please refer com.tirthal.learning.oop.concepts.Delegation_TestDrive
4 | /**
5 | * Modem class using Delegation design principle.
6 | *
7 | * @author tirthalp
8 | *
9 | */
10 | public class Modem implements IConnection, IDataChannel {
11 |
12 | private IConnection connection;
13 | private IDataChannel dataChannel;
14 |
15 | public Modem(IConnection connection, IDataChannel dataChannel) {
16 | this.connection = connection;
17 | this.dataChannel = dataChannel;
18 | }
19 |
20 | @Override
21 | public void dial(String phoneNumber) {
22 | connection.dial(phoneNumber);
23 | }
24 |
25 | @Override
26 | public void disconnect() {
27 | connection.disconnect();
28 | }
29 |
30 | @Override
31 | public void send(char c) {
32 | dataChannel.send(c);
33 | }
34 |
35 | @Override
36 | public char receive() {
37 | return dataChannel.receive();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/good/ModemFastClient.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.good;
2 |
3 |
4 | /**
5 | * @author tirthalp
6 | *
7 | */
8 | public class ModemFastClient {
9 |
10 | public static void main(String[] args) {
11 |
12 | Modem modem = new Modem(new ConnectionManager(), new DataChannelFastMode());
13 |
14 | modem.dial("0000000000");
15 | modem.send('t');
16 | modem.receive();
17 | modem.disconnect();
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/DesignPrinciples/src/com/tirthal/learning/oop/design/principles/clazz/solid/srp/modem/good/ModemSlowClient.java:
--------------------------------------------------------------------------------
1 | package com.tirthal.learning.oop.design.principles.clazz.solid.srp.modem.good;
2 |
3 | /**
4 | * @author tirthalp
5 | *
6 | */
7 | public class ModemSlowClient {
8 |
9 | public static void main(String[] args) {
10 |
11 | Modem modem = new Modem(new ConnectionManager(), new DataChannelSlowMode());
12 |
13 | modem.dial("0000000000");
14 | modem.send('t');
15 | modem.receive();
16 | modem.disconnect();
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Tirthal Patel
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Learning-OOPD
2 | =============
3 |
4 | Sample java code for learning object oriented programming design principles and patterns
5 |
6 |
7 | DesignPrinciples
8 | -----------------
9 |
10 | For more detail, please refer [here](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPrinciples)
11 |
12 |
13 | DesignPatterns
14 | --------------
15 |
16 | For more detail, please refer [here](https://github.com/tirthalpatel/Learning-OOPD/tree/master/DesignPatterns)
--------------------------------------------------------------------------------