├── .gitignore
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── com
│ └── braindevoiler
│ └── designpattern
│ ├── behavioral
│ ├── chainofresponsibility
│ │ └── ChainOfResponsibilityTest.java
│ ├── command
│ │ ├── Command.java
│ │ ├── CommandTest.java
│ │ ├── Light.java
│ │ ├── LightOffCommand.java
│ │ ├── LightOnCommand.java
│ │ ├── NoCommand.java
│ │ └── SimpleRemoteControl.java
│ ├── interpreter
│ │ └── InterpreterTest.java
│ ├── iterator
│ │ ├── DinerMenu.java
│ │ ├── DinerMenuIterator.java
│ │ ├── IteratorTest.java
│ │ ├── Menu.java
│ │ ├── MenuItem.java
│ │ ├── PancakeHouseMenu.java
│ │ └── Waitress.java
│ ├── mediator
│ │ └── MediatorTest.java
│ ├── memento
│ │ └── MementoTest.java
│ ├── observer
│ │ ├── CurrentConditionsDisplay.java
│ │ ├── DisplayElement.java
│ │ ├── ForecastDisplay.java
│ │ ├── Observer.java
│ │ ├── ObserverTest.java
│ │ ├── Subject.java
│ │ └── WeatherData.java
│ ├── state
│ │ ├── GumballMachine.java
│ │ ├── HasQuarterState.java
│ │ ├── NoQuarterState.java
│ │ ├── SoldOutState.java
│ │ ├── SoldState.java
│ │ ├── State.java
│ │ └── StateTest.java
│ ├── strategy
│ │ ├── Duck.java
│ │ ├── FlyBehavior.java
│ │ ├── FlyNoWay.java
│ │ ├── FlyWithWings.java
│ │ ├── MallardDuck.java
│ │ ├── Quack.java
│ │ ├── QuackBehavior.java
│ │ ├── RedheadDuck.java
│ │ ├── Squeak.java
│ │ └── StrategyTest.java
│ ├── template
│ │ ├── CaffeineBeverage.java
│ │ ├── Coffee.java
│ │ ├── Tea.java
│ │ └── TemplateTest.java
│ └── visitor
│ │ └── VisitorTest.java
│ ├── creational
│ ├── abstractfactory
│ │ ├── AbstractFactoryTest.java
│ │ ├── PizzaType.java
│ │ ├── pizza
│ │ │ ├── CheesePizza.java
│ │ │ ├── ClamPizza.java
│ │ │ ├── PepperoniPizza.java
│ │ │ ├── Pizza.java
│ │ │ └── VeggiePizza.java
│ │ ├── pizzaingredient
│ │ │ ├── Cheese.java
│ │ │ ├── Clams.java
│ │ │ ├── Dough.java
│ │ │ ├── FreshClams.java
│ │ │ ├── FrozenClams.java
│ │ │ ├── MarinaraSauce.java
│ │ │ ├── MozzarellaCheese.java
│ │ │ ├── Pepperoni.java
│ │ │ ├── PlumTomatoSauce.java
│ │ │ ├── ReggianoCheese.java
│ │ │ ├── Sauce.java
│ │ │ ├── SlicedPepperoni.java
│ │ │ ├── ThickCrustDough.java
│ │ │ ├── ThinCrustDough.java
│ │ │ └── Veggies.java
│ │ ├── pizzaingredientfactory
│ │ │ ├── ChicagoPizzaIngredientFactory.java
│ │ │ ├── NYPizzaIngredientFactory.java
│ │ │ └── PizzaIngredientFactory.java
│ │ └── pizzastore
│ │ │ ├── ChicagoPizzaStore.java
│ │ │ ├── NYPizzaStore.java
│ │ │ └── PizzaStore.java
│ ├── builder
│ │ ├── BuilderTest.java
│ │ └── Computer.java
│ ├── factorymethod
│ │ ├── FactoryMethodTest.java
│ │ ├── PizzaType.java
│ │ ├── pizza
│ │ │ ├── ChicagoStyleCheesePizza.java
│ │ │ ├── ChicagoStyleClamPizza.java
│ │ │ ├── ChicagoStylePepperoniPizza.java
│ │ │ ├── ChicagoStyleVeggiePizza.java
│ │ │ ├── NYStyleCheesePizza.java
│ │ │ ├── NYStyleClamPizza.java
│ │ │ ├── NYStylePepperoniPizza.java
│ │ │ ├── NYStyleVeggiePizza.java
│ │ │ └── Pizza.java
│ │ └── pizzastore
│ │ │ ├── ChicagoStylePizzaStore.java
│ │ │ ├── NYStylePizzaStore.java
│ │ │ └── PizzaStore.java
│ ├── prototype
│ │ ├── Employees.java
│ │ └── PrototypeTest.java
│ ├── simplefactory
│ │ ├── PizzaStore.java
│ │ ├── PizzaType.java
│ │ ├── SimpleFactoryTest.java
│ │ ├── SimplePizzaFactory.java
│ │ └── pizza
│ │ │ ├── CheesePizza.java
│ │ │ ├── ClamPizza.java
│ │ │ ├── PepperoniPizza.java
│ │ │ ├── Pizza.java
│ │ │ └── VeggiePizza.java
│ └── singleton
│ │ ├── Singleton.java
│ │ └── SingletonTest.java
│ └── structural
│ ├── adapter
│ ├── AdapterTest.java
│ ├── Duck.java
│ ├── MallardDuck.java
│ ├── Turkey.java
│ ├── TurkeyAdapter.java
│ └── WildTurkey.java
│ ├── bridge
│ ├── BridgeTest.java
│ ├── ConcreteRemote.java
│ ├── RemoteControl.java
│ ├── SamsungTv.java
│ ├── SonyTv.java
│ └── Tv.java
│ ├── composite
│ ├── CompositeTest.java
│ ├── Menu.java
│ ├── MenuComponent.java
│ ├── MenuItem.java
│ └── Waitress.java
│ ├── decorator
│ ├── Beverage.java
│ ├── CondimentDecorator.java
│ ├── DarkRoast.java
│ ├── Decaf.java
│ ├── DecoratorTest.java
│ ├── Espresso.java
│ ├── HouseBlend.java
│ ├── Milk.java
│ ├── Mocha.java
│ ├── Soy.java
│ └── Whip.java
│ ├── facade
│ ├── Amplifier.java
│ ├── DvdPlayer.java
│ ├── FacadeTest.java
│ ├── HomeTheaterFacade.java
│ ├── Projector.java
│ ├── Screen.java
│ └── TheaterLights.java
│ ├── flyweight
│ ├── Circle.java
│ ├── FlyweightTest.java
│ ├── Shape.java
│ └── ShapeFactory.java
│ └── proxy
│ ├── GumballMachine.java
│ ├── GumballMachineRemoteProxy.java
│ ├── GumballMachineRemoteProxyTest.java
│ ├── GumballMachineSetup.java
│ └── machinestate
│ ├── HasQuarterState.java
│ ├── NoQuarterState.java
│ ├── SoldOutState.java
│ ├── SoldState.java
│ └── State.java
└── test
└── java
└── com
└── braindevoiler
└── designpattern
└── AppTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | target/
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Design Principles
2 |
3 | ### 1. Identify the aspects of your application that vary and separate them from what stays the same.
4 | * Take what varies and encapsulate it so it won't affect the rest of your code.
5 | * It results in fewer unintended consequences from code changes and more flexibility in your system.
6 |
7 | ### 2. Program to an interface, not an implementation.
8 |
9 | ### 3. Favor composition over inheritance.
10 | * It gives us more flexibility.
11 | * It lets us change behavior at runtime.
12 |
13 | ### 4. Strive for loosely coupled designs between objects that interact.
14 | * Loosely coupled designs allow us to build flexible OO systems that can handle change because they minimize the
15 | interdependency between objects.
16 |
17 | ### 5. The Open-Closed Principle
18 | * Classes should be open for extension, but closed for modification.
19 | * Allow classes to be easily extended to incorporate new behavior without modifying existing code.
20 | * Applying the Open-Closed Principle everywhere is wasteful, unnecessary, and can lead to complex, hard to understand
21 | code. We should concentrate on those areas that are most likely to change in the design.
22 |
23 | ### 6. The Dependency Inversion Principle
24 | * Depend upon abstractions. Do not depend upon concrete classes.
25 | * High level components should not depend on low-level components, rather, they should both depend on abstractions.
26 | * Guidelines:
27 | * No variable should hold a reference to a concrete class.
28 | * No class should derive from a concrete class.
29 | * No method should override an implemented method of any of its base classes.
30 |
31 | ### 7. The Principle of Least Knowledge/The Law of Demeter : Talk only to your immediate friends.
32 | * It means when you are designing a system, for any object, be careful of the number of classes it interacts with and
33 | also how it comes to interact with those classes.
34 | * This principle prevents us from creating designs that have a large number of classes coupled together so that
35 | changes in one part of the system cascade to other parts.
36 | * How do you keep from doing this? The principle provides some guidelines: take any object; now from any method in
37 | that object, the principle tells us that we should only invoke methods that belong to:
38 | * The object itself
39 | * Objects passed in as a parameter to the method
40 | * Any object the method creates or instantiates
41 | * Any components of the object (Object composition, has-a-relationship)
42 | * Above guidelines tells us not to call methods on objects that were returned from calling other methods.
43 |
44 | Without the principle:
45 | ```
46 | public float getTemp() {
47 | Thermometer thermometer = station.getThermometer();
48 | return thermometer.getTemperature();
49 | }
50 | ```
51 |
52 | With the principle:
53 | ```
54 | public float getTemp() {
55 | return station.getTemperature();
56 | }
57 | ```
58 |
59 | #### Disadvantages of applying the Principle of Least Knowledge;
60 | * While the principle reduces the dependencies between objects and studies have shown this reduces software
61 | maintenance, it is also the case that applying this principle results in more "wrapper" classes being written to
62 | handle method calls to other components. This can result in increased complexity and development time as well as
63 | decreased runtime performance.
64 |
65 | ### 8. The Hollywoon Principle: Don't call us, we'll call you. (Template Method Pattern)
66 | * Allow low-level components to hook themselves into a system, but the high level components determine when they are
67 | needed, and how.
68 | * The high-level components give the low-level components a "don't call us, we'll call you" treatment.
69 |
70 | ### 9. Single Responsibility
71 | * A class should have only one reason to change.
72 | * Every responsibility of a class is an area of potential change. More than one responsibility means more than one
73 | area of change.
74 | * A class has high cohesion when it is designed around a set of related functions, and we say that it has low
75 | cohesion when it's designed around a set of unrelated functions.
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 | 4.0.0
6 |
7 | com.braindevoiler
8 | design-patterns
9 | 1.0-SNAPSHOT
10 |
11 | design-patterns
12 | Project to learn Object Oriented Design Patterns
13 | https://github.com/braindevoiler/design-patterns
14 |
15 |
16 | MIT License
17 | https://opensource.org/licenses/MIT
18 |
19 |
20 |
21 |
22 | Ankur Gupta
23 | info@ankurgupta.net
24 |
25 |
26 |
27 | https://github.com/braindevoiler/design-patterns
28 |
29 |
30 | UTF-8
31 | 1.8
32 | 1.8
33 | 1.8
34 | 1.2.3
35 | 4.13.1
36 | 1.18.12
37 |
38 |
39 |
40 |
41 | junit
42 | junit
43 | ${junit.version}
44 | test
45 |
46 |
47 | ch.qos.logback
48 | logback-classic
49 | ${logback.version}
50 |
51 |
52 | org.projectlombok
53 | lombok
54 | ${lombok.version}
55 | provided
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/src/main/java/com/braindevoiler/designpattern/behavioral/chainofresponsibility/ChainOfResponsibilityTest.java:
--------------------------------------------------------------------------------
1 | package com.braindevoiler.designpattern.behavioral.chainofresponsibility;
2 |
3 | public class ChainOfResponsibilityTest {
4 | /**
5 | * With the Chain of Responsibility Pattern, you create a chain of objects that examine a request. Each object in
6 | * turn examines the request and handles it, or passes it on to the next object in the chain.
7 | *
8 | * Use the Chain of Responsibility Pattern when you want to give more than one object a chance to handle a request.
9 | *
10 | * Each object in the chain acts as a handler and has a successor object. If it can handle the request, it does;
11 | * otherwise, it forwards the request to its successor.
12 | *
13 | * It allows you to add or remove responsibilities dynamically by changing the members or order of the chain.
14 | *
15 | * Example: Spam filter rules in mailing application.
16 | */
17 | public static void main(String[] args) {
18 |
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/braindevoiler/designpattern/behavioral/command/Command.java:
--------------------------------------------------------------------------------
1 | package com.braindevoiler.designpattern.behavioral.command;
2 |
3 | public interface Command {
4 | void execute();
5 |
6 | void undo();
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/braindevoiler/designpattern/behavioral/command/CommandTest.java:
--------------------------------------------------------------------------------
1 | package com.braindevoiler.designpattern.behavioral.command;
2 |
3 | public class CommandTest {
4 | /**
5 | * The Command Pattern encapsulates a request as an object, thereby letting you parameterize other objects with
6 | * different requests, queue or log requests, and support undoable operations.
7 | */
8 | public static void main(String[] args) {
9 | SimpleRemoteControl remote = new SimpleRemoteControl();
10 | Light light = new Light();
11 | Command lightOn = new LightOnCommand(light);
12 | Command lightOff = new LightOffCommand(light);
13 | remote.setCommand(0, lightOn, lightOff);
14 | remote.onButtonPressed(0);
15 | remote.offButtonPressed(0);
16 | remote.undoButtonPressed();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/braindevoiler/designpattern/behavioral/command/Light.java:
--------------------------------------------------------------------------------
1 | package com.braindevoiler.designpattern.behavioral.command;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 |
7 | public class Light {
8 | private static final Logger LOGGER = LoggerFactory.getLogger(Light.class);
9 |
10 | public void on() {
11 | LOGGER.info("Switching on light");
12 | }
13 |
14 | public void off() {
15 | LOGGER.info("Switching off light");
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/braindevoiler/designpattern/behavioral/command/LightOffCommand.java:
--------------------------------------------------------------------------------
1 | package com.braindevoiler.designpattern.behavioral.command;
2 |
3 | public class LightOffCommand implements Command {
4 | Light light;
5 |
6 | public LightOffCommand(Light light) {
7 | this.light = light;
8 | }
9 |
10 | public void execute() {
11 | light.off();
12 | }
13 |
14 | public void undo() {
15 | light.on();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/braindevoiler/designpattern/behavioral/command/LightOnCommand.java:
--------------------------------------------------------------------------------
1 | package com.braindevoiler.designpattern.behavioral.command;
2 |
3 | public class LightOnCommand implements Command {
4 | Light light;
5 |
6 | public LightOnCommand(Light light) {
7 | this.light = light;
8 | }
9 |
10 | public void execute() {
11 | light.on();
12 | }
13 |
14 | public void undo() {
15 | light.off();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/braindevoiler/designpattern/behavioral/command/NoCommand.java:
--------------------------------------------------------------------------------
1 | package com.braindevoiler.designpattern.behavioral.command;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 |
7 | public class NoCommand implements Command {
8 | private static final Logger LOGGER = LoggerFactory.getLogger(NoCommand.class);
9 |
10 | @Override
11 | public void execute() {
12 | LOGGER.info("Do Nothing");
13 | }
14 |
15 | @Override
16 | public void undo() {
17 | LOGGER.info("Undo Nothing");
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/braindevoiler/designpattern/behavioral/command/SimpleRemoteControl.java:
--------------------------------------------------------------------------------
1 | package com.braindevoiler.designpattern.behavioral.command;
2 |
3 | public class SimpleRemoteControl {
4 | private static final int COUNT_COMMANDS = 1;
5 | private final Command[] onCommands;
6 | private final Command[] offCommands;
7 | private Command undoCommand;
8 |
9 | public SimpleRemoteControl() {
10 | onCommands = new Command[COUNT_COMMANDS];
11 | offCommands = new Command[COUNT_COMMANDS];
12 | Command noCommand = new NoCommand();
13 | for (int i = 0; i < COUNT_COMMANDS; i++) {
14 | onCommands[i] = noCommand;
15 | offCommands[i] = noCommand;
16 | }
17 | undoCommand = noCommand;
18 | }
19 |
20 | public void setCommand(int slot, Command onCommand, Command offCommand) {
21 | onCommands[slot] = onCommand;
22 | offCommands[slot] = offCommand;
23 | }
24 |
25 | public void onButtonPressed(int slot) {
26 | onCommands[slot].execute();
27 | undoCommand = onCommands[slot];
28 | }
29 |
30 | public void offButtonPressed(int slot) {
31 | offCommands[slot].execute();
32 | undoCommand = offCommands[slot];
33 | }
34 |
35 | public void undoButtonPressed() {
36 | undoCommand.undo();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/braindevoiler/designpattern/behavioral/interpreter/InterpreterTest.java:
--------------------------------------------------------------------------------
1 | package com.braindevoiler.designpattern.behavioral.interpreter;
2 |
3 | public class InterpreterTest {
4 | /**
5 | * Use the Interpreter Pattern to build an interpreter for a language.
6 | *
7 | * When you need to implement a simple language, the Interpreter Pattern defines a class-based representation for
8 | * its grammar along with an interpreter to interpret its sentences. To represent the language, you use a class
9 | * to represent each rule in the language.
10 | *
11 | * Representing each grammar rule in a class makes the language easy to implement.
12 | *
13 | * Because the grammar is represented by classes, you can easily change or extend the language.
14 | *
15 | * Appropriate when you have a simple grammar and simplicity is more important than efficiency.
16 | */
17 | public static void main(String[] args) {
18 |
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/braindevoiler/designpattern/behavioral/iterator/DinerMenu.java:
--------------------------------------------------------------------------------
1 | package com.braindevoiler.designpattern.behavioral.iterator;
2 |
3 | import java.util.Iterator;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 |
8 | public class DinerMenu implements Menu {
9 | private static final Logger LOGGER = LoggerFactory.getLogger(DinerMenu.class);
10 |
11 | private static final int MAX_ITEMS = 6;
12 | private final MenuItem[] menuItems;
13 | private int numberOfItems = 0;
14 |
15 | public DinerMenu() {
16 | menuItems = new MenuItem[MAX_ITEMS];
17 |
18 | addItem("Vegetarian BLT",
19 | "(Fakin') Bacon with lettuce & tomato on whole wheat",
20 | true, 2.99);
21 | addItem("BLT",
22 | "Bacon with lettuce & tomato on false wheat",
23 | true, 2.99);
24 | addItem("Soup of the day",
25 | "Soup of the day, with a side of potato salad",
26 | false, 3.29);
27 | addItem("Hotdog",
28 | "A hot dog, with a side of potato salad",
29 | false, 3.05);
30 | }
31 |
32 | public void addItem(String name, String description, boolean vegetarian, double price) {
33 | MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
34 | if (numberOfItems >= MAX_ITEMS) {
35 | LOGGER.info("Sorry, menu is full! Can't add item to menu");
36 | } else {
37 | menuItems[numberOfItems] = menuItem;
38 | numberOfItems = numberOfItems + 1;
39 | }
40 | }
41 |
42 | @Override
43 | public Iterator