
Preview the three-part course structure covering design patterns (Gang of Four), pattern classification, and SOLID design principles. Meet the Java prerequisite of at least three months of programming experience.
Set up your Java development environment with any IDE, import the Maven project containing pom.xml, and configure the Java compiler to version 8 to run and explore the code.
Define a design pattern as a documented solution to recurring object-oriented design problems, detailing when it applies and trade-offs, in the patterns catalog from the 1995 Gang of Four book.
Explore the mediator pattern through a cricket-inspired scenario, showing how batsman, umpire, and bowler exchange signals (six, out, no ball, free hit) and reveal design issues.
This lecture highlights design issues where batsman directly informs the bowler, creating tight coupling and poor reusability, with future changes needing many new subclasses and cross-class edits.
Learn how a cricket mediator coordinates batsman, bowler, and umpire, handling states six, out, no ball, and free hit. This mediator design reduces tight coupling and eases adding classes.
Add a new WicketKeeper class to the Game and implement rules: when Batsman hits a six or when Bowler bowls a NoBall, the wicketkeeper gets frustrated; solution discussed next lecture.
Apply the mediator pattern using a WicketKeeper and CricketMediator to trigger frustration when batsman hits a six or bowler delivers a no ball.
Explore the mediator pattern, an object that encapsulates how a set of objects interact. Promote loose coupling and let you vary interactions independently, as illustrated by the cricket mediator.
Explore when to use the mediator pattern, its decoupling of colleagues via a central mediator, and the balance of advantages and potential complexity.
Explore the iterator pattern by traversing an instructor’s course list to advertise on YouTube and Facebook. See how the advertise methods fetch and print each course’s id and name.
Examine loose coupling as changing the Instructor's courses data structure (array, ArrayList, HashMap) forces YouTube and FaceBook to alter iteration, revealing a bad design and prompting a solution.
Explore a design pattern where CourseIterator implements hasNext and next to traverse a courses array; an instructor can createIterator, and changing to arrayList does not affect YouTube and Facebook advertise.
Convert the courses data structure from an array to ArrayList and update the CourseIterator, then test hasNext and next to ensure Facebook and YouTube require no edits.
The lecture reviews converting courses from array to list and updating the instructor and courseiterator classes to reach the final design, noting YouTube and Facebook remain unchanged.
Explore the iterator pattern in Java, enabling sequential traversal of an aggregate without exposing its internal representation, using hasNext and next, and decoupling client from concrete data structures.
Replace the custom Iterator interface in the project with java.util.Iterator and prepare to review the solution in the next lecture.
Replace the interface with java.util.Iterator across the project, including Facebook and Youtube classes, and confirm the application works using has next and next methods.
Learn the iterator pattern to hide complex data structures, reduce traversal code duplication, and enable traversal of different or unknown data structures with parallel iteration, respecting the open-closed principle.
Through flyweight design pattern concepts, this lecture shows a Tree interface implemented by CoconutTree and RoseTree, drawing trees at coordinates, with a plant tree action duplicating objects and tracking totalObjects.
This lecture demonstrates a Java design patterns example. Pressing plantTrees creates coconut and rose trees via a Tree interface, updates totalObjects counter, and draws each tree with coordinates and colors.
Test real-time game performance by illustrating how 10 objects are created per click, potentially reaching 1 million objects after 100k clicks, and propose reusing created objects to improve memory efficiency.
TreeFactory uses a hashmap to create a coconut tree on first request and reuse it later, while the Tree interface adds a draw method to decouple Forest from concrete trees.
Explore the flyweight pattern in action as the forest delegates object creation to TreeFactory, which reuses two shared tree instances via getTree and a hashmap.
Define the flyweight design pattern to share objects and support large numbers of fine-grained objects efficiently, using intrinsic attributes shared by all flyweights and extrinsic state managed by clients.
Explore the flyweight pattern in Java patterns, including when to apply it for many objects and high storage costs, how extrinsic state enables variety, and the trade-offs around object identity.
Explore the strategy pattern through a bird game example, detailing default and overridden methods for display, fly, run, swim, and kill.
this lecture examines how a default kill method in a base class affects all subclasses and how overriding it with empty implementations can meet client requirements.
Explore how replacing inheritance with a Killable interface refines the design, enabling only killer birds like Vulture and Ostrich to implement the kill method.
Analyze shift from a class with a default kill method to Killable. Show Parrot and Peacock without a kill method; Vulture and Ostrich share kill logic.
Identify the aspects that vary and program to an interface, then demonstrate runtime polymorphism with KillBehavior and concrete classes such as KillWithBeak, KillWithLegs, KillNoWay, and KillWithBody.
Learn how a flexible design encapsulates killing behavior in a single class, avoids redundant code, and uses setters to enable dynamic behavior changes.
Explore how the KillBehavior interface and its implementations (KillWithBeak, KillWithBody, KillWithLegs, KillNoWay) steer a Bird's kill action. See how the eagle's default KillWithBeak demonstrates dynamic changes in behavior via composition.
Implement a new bird subclass AlienBird in Java, building on prior patterns where Eagle uses beak and Ostrich uses body; AlienBird kills with its eyes.
Demonstrate dynamic kill behavior in AlienBird by implementing KillBehavior, initially using KillNoWay, then switching to KillWithEyes via setKillBehavior to enable killing with eyes.
Compare is-a and has-a relationships to show inheritance and composition in Java design patterns, and demonstrate how composition enables runtime behavior changes with strategy pattern.
Discover how the strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable, letting the algorithm vary independently from the clients that use it.
Explore the strategy design pattern by implementing a Payable interface with pay with GooglePay, pay with net banking, and pay with Paytm, while online store delegates payments via makePayment.
Explore the strategy pattern to select and exchange algorithms at run-time, achieve the open-closed principle, and replace conditional logic with a single configurable class.
This lecture illustrates the singleton design pattern by showing three departments sharing a single printer and the problem when each department uses its own printer instance.
Departments share a single printer instance by passing a common Printer to all classes, avoiding external dependencies. The team suggests converting Printer to a singleton for the next lecture.
Discover how a singleton class ensures only one object exists and is shared across all classes, unlike multiple independent instances.
Turn the printer into a singleton by a private constructor and a static getInstance, creating a single globally shared object; the lesson shows 50 paper requests and out of stock.
Review how a private constructor creates a singleton, initialize a static unique instance, and expose a getInstance method to share the printer across departments.
Explore the singleton pattern, which ensures a class has only one instance and provides a global access point, illustrated by the Printer singleton and its getInstance method.
Illustrates how lazy initialization in a singleton's getInstance can lead to two objects under multi-threading, and shows how eager initialization guarantees a thread-safe, unique instance.
Explore when to apply the singleton pattern and its memory benefits. Learn the testing and multi-threading challenges, and real-time examples like logger, utility classes, dao classes, and config files.
Explore the observer design pattern and contrast tight coupling with loose coupling using a vehicle interface, a car, and a journey class, illustrating how changes propagate.
Explore the observer pattern by modeling YouTube subscriptions, where the channel acts as the subject and subscribers as observers, receiving notifications when videos are added, including subscribe and unsubscribe dynamics.
Create a publisher-subscriber setup: define YouTube channel and subscriber interfaces, implement IccCricInfo channel, concrete subscribers, and notify on new videos.
Explore the observer design pattern with a publisher (channel) and subscribers. Learn loose coupling via interfaces, attach/detach/notify mechanics, and how changes propagate to all subscribers.
The observer design pattern defines a one-to-many dependency where a subject notifies its observers of state changes, using registerObserver, removeObserver, and notifyObservers.
Explore the observer pattern that promotes loose coupling between subjects and observers and learn push and pull data variants with publishers and subscribers.
Implement the pull variant by letting the publisher pass itself to subscribers, who extract state and videos via exposed methods, completing the pull design.
Compare the push and pull design patterns in Java, where push passes changed data to observers and pull provides the subject for observers to fetch data.
Explore the observer design pattern as a publisher and subscribers with loosely coupled components, learn push and pull variants, advantages of decoupling, and practical Java implementations.
Explore the template method pattern by comparing cement, wooden, and iron houses; follow a shared algorithm to build foundation, walls, windows, and roof, then analyze design issues.
Analyze how code duplication across multiple classes signals design pattern flaws, and learn to refactor to encapsulate the algorithm, reducing edits and centralizing behavior.
Explore how the template method pattern refactors a house design in Java, with an abstract base class, a final buildHouse, abstract buildWalls and buildRoof, and concrete CementHouse, WoodenHouse, and IronHouse.
Define the template method pattern as the skeleton of an algorithm, deferring steps to subclasses via abstract methods like buildWalls and buildRoof in an abstract class, preserving the algorithm's structure.
Explore hooks in design patterns, showing how an abstract class provides a default hook like isFoundationRequired that subclasses can override to conditionally control an algorithm, such as building a foundation.
Explore the Template Method Pattern, defining the skeleton of an algorithm and deferring steps to subclasses, so invariant and variant parts can be managed without changing the structure.
Learn how decorating extends behavior without modifying code, via the decorator pattern illustrated with a Baby and BabySpeakingDecorator adding speaking alongside walking, respecting the open-closed principle.
Examine how the AnimalHunt game models running, climbing, and killing across difficulty levels using Animal, Lion, Tiger, and Leopard, contrasting inheritance with the decorating approach that adds few new classes.
Compare how the decorator pattern adds climbing and killing abilities to animals via AnimalDecorator, AnimalClimbingDecorator, and AnimalKillingDecorator, offering a flexible alternative to inheritance.
Learn how the decorator pattern adds functionality to an object dynamically, using a component Animal, component Lion, decorator AnimalDecorator, and concrete decorators AnimalClimbingDecorator and AnimalKillingDecorator, a flexible alternative to subclassing.
Explore how the decorator pattern extends a soup ordering system by adding venegar and pepper to TomatoSoup and ChickenSoup orders.
Understand the decorator pattern in Java through a soup ordering example, where tomato soup costs 100, chicken soup 200, and vinegar and pepper decorators add 20 each.
Illustrates how the decorator pattern adds responsibilities to an object dynamically, as an alternative to subclassing, using Java's FileInputStream, BufferedInputStream, and LineNumberInputStream as examples; explains advantages and when to apply.
Welcome!
My name is Harshith Gandham, and I am going to be the Instructor to this Course.
The intent of this course is to convert you into an "Experienced Object-Oriented Designer".
Hence, By the end of this course,
You will be able to design reusable and flexible object-oriented software, with ease.
Your design, apart from being specific to the problem at hand, will also be general enough to address future problems and requirements.
You will be able to pinpoint maintainability and extensibility problems in existing designs.
You will be able to design "right" faster.
Finally, You will be a better developer than now.
Inorder to take this course, it is mandatory to have atleast 3 months of programming experience in java.
This course comes with a 30-days money back guarantee.
So, there is really nothing you loose.
By the end of this course,
You will be able to design reusable and flexible object-oriented software, with ease.
Your design, apart from being specific to the problem at hand, will also be general enough to address future problems and requirements.
You will be able to pinpoint maintainability and extensibility problems in existing designs.
You will be able to design "right" faster.
Finally, You will be a better developer than now.