diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..c47557a
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..aa00ffa
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
new file mode 100644
index 0000000..712ab9d
--- /dev/null
+++ b/.idea/jarRepositories.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/java-deisgn-patterns.iml b/.idea/java-deisgn-patterns.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/.idea/java-deisgn-patterns.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..4258c62
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index d4ff426..7c02993 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,14 @@
## About the Course
-Design patterns are proven solutions to common software design problems, helping developers create scalable, maintainable, and efficient applications. This **Java Design Patterns** course covers essential patterns from all three major categories:
+Design patterns are proven solutions to common software design problems, helping developers create scalable, maintainable, and efficient applications. This **Java Design Patterns** course covers essential patterns from all three major categories.
+
+### Important Links
+- Video (free) Course Link: [Java Design Patterns](https://www.youtube.com/playlist?list=PL5DyztRVgtRUqnoWYVAFC1honDiDpdKOX)
+- Connect on
+ - [LinkedIn](https://www.linkedin.com/in/waqar-ahmad-cnc/)
+ - [Youtube](https://www.youtube.com/@codencode)
+ - [Instagram](https://www.instagram.com/code_ncode/?hl=en)
### 1. Creational Patterns
Focus on object creation mechanisms to improve flexibility and reuse.
diff --git a/creational/FactoryMethod/preffered/client/Main.java b/creational/FactoryMethod/preffered/client/Main.java
deleted file mode 100644
index 4b86f4a..0000000
--- a/creational/FactoryMethod/preffered/client/Main.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.codencode.preffered.client;
-
-import com.codencode.preffered.library.factory.SMSNotificationFactory;
-import com.codencode.preffered.library.notification.Notification;
-
-public class Main {
- public static void main(String[] args) {
- Notification notification = new SMSNotificationFactory().createNotification();
-
- notification.notifyUser();
- }
-}
\ No newline at end of file
diff --git a/creational/FactoryMethod/preffered/library/factory/EmailNotificationFactory.java b/creational/FactoryMethod/preffered/library/factory/EmailNotificationFactory.java
deleted file mode 100644
index 4ec5c16..0000000
--- a/creational/FactoryMethod/preffered/library/factory/EmailNotificationFactory.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.codencode.preffered.library.factory;
-
-import com.codencode.preffered.library.notification.EmailNotification;
-import com.codencode.preffered.library.notification.Notification;
-
-public class EmailNotificationFactory implements NotificationFactory{
- @Override
- public Notification createNotification() {
- return new EmailNotification();
- }
-}
diff --git a/creational/FactoryMethod/preffered/library/factory/NotificationFactory.java b/creational/FactoryMethod/preffered/library/factory/NotificationFactory.java
deleted file mode 100644
index 25f04b3..0000000
--- a/creational/FactoryMethod/preffered/library/factory/NotificationFactory.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.codencode.preffered.library.factory;
-
-import com.codencode.preffered.library.notification.Notification;
-
-public interface NotificationFactory {
- public Notification createNotification();
-}
diff --git a/creational/FactoryMethod/preffered/library/factory/PushNotificationFactory.java b/creational/FactoryMethod/preffered/library/factory/PushNotificationFactory.java
deleted file mode 100644
index 29b74e8..0000000
--- a/creational/FactoryMethod/preffered/library/factory/PushNotificationFactory.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.codencode.preffered.library.factory;
-
-import com.codencode.preffered.library.notification.Notification;
-import com.codencode.preffered.library.notification.PushNotification;
-
-public class PushNotificationFactory implements NotificationFactory{
- @Override
- public Notification createNotification() {
- return new PushNotification();
- }
-}
diff --git a/creational/FactoryMethod/preffered/library/factory/SMSNotificationFactory.java b/creational/FactoryMethod/preffered/library/factory/SMSNotificationFactory.java
deleted file mode 100644
index aa4428e..0000000
--- a/creational/FactoryMethod/preffered/library/factory/SMSNotificationFactory.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.codencode.preffered.library.factory;
-
-import com.codencode.preffered.library.notification.Notification;
-import com.codencode.preffered.library.notification.SMSNotification;
-
-public class SMSNotificationFactory implements NotificationFactory{
- @Override
- public Notification createNotification() {
- return new SMSNotification();
- }
-}
diff --git a/creational/FactoryMethod/preffered/library/notification/Notification.java b/creational/FactoryMethod/preffered/library/notification/Notification.java
deleted file mode 100644
index 16278e4..0000000
--- a/creational/FactoryMethod/preffered/library/notification/Notification.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.codencode.preffered.library.notification;
-
-public interface Notification {
- void notifyUser();
-}
diff --git a/creational/FactoryMethod/simple/client/Main.java b/creational/FactoryMethod/simple/client/Main.java
deleted file mode 100644
index b998dc6..0000000
--- a/creational/FactoryMethod/simple/client/Main.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.codencode.simple.client;
-
-import com.codencode.simple.library.CompilerFactory;
-import com.codencode.simple.library.compiler.Compiler;
-import com.codencode.simple.library.compiler.CompilerType;
-
-public class Main {
- public static void main(String[] args) {
- Compiler compiler = CompilerFactory.getCompiler(CompilerType.JAVA);
-
- System.out.println(compiler.compile("c"));
- }
-}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..44d92f5
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,17 @@
+
+
+ 4.0.0
+
+ design-patterns
+ java-deisgn-patterns
+ 1.0-SNAPSHOT
+
+
+ 18
+ 18
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/src/main/java/behavioral/Observer/Main.java b/src/main/java/behavioral/Observer/Main.java
new file mode 100644
index 0000000..8f22854
--- /dev/null
+++ b/src/main/java/behavioral/Observer/Main.java
@@ -0,0 +1,23 @@
+package com.codencode;
+
+import com.codencode.observer.ConsoleLogger;
+import com.codencode.observer.FileLogger;
+import com.codencode.observer.Observer;
+import com.codencode.subject.Stock;
+
+public class Main {
+ public static void main(String[] args) {
+ Stock tcs = new Stock("TCS", 3500.00);
+
+ Observer consoleLogger = new ConsoleLogger();
+ Observer fileLogger = new FileLogger("prices.log");
+
+ tcs.attach(consoleLogger);
+ tcs.attach(fileLogger);
+
+ tcs.startPriceFeed(); // Price changes every 5 seconds
+
+ // keep main thread alive (for demo purpose)
+ try { Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); }
+ }
+}
diff --git a/src/main/java/behavioral/Observer/observer/ConsoleLogger.java b/src/main/java/behavioral/Observer/observer/ConsoleLogger.java
new file mode 100644
index 0000000..574d13c
--- /dev/null
+++ b/src/main/java/behavioral/Observer/observer/ConsoleLogger.java
@@ -0,0 +1,10 @@
+package com.codencode.observer;
+
+import java.time.LocalDateTime;
+
+public class ConsoleLogger implements Observer {
+ @Override
+ public void update(String symbol, double price) {
+ System.out.println(LocalDateTime.now() + " | " + symbol + " price: " + price);
+ }
+}
diff --git a/src/main/java/behavioral/Observer/observer/FileLogger.java b/src/main/java/behavioral/Observer/observer/FileLogger.java
new file mode 100644
index 0000000..8aafbb0
--- /dev/null
+++ b/src/main/java/behavioral/Observer/observer/FileLogger.java
@@ -0,0 +1,22 @@
+package com.codencode.observer;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.time.LocalDateTime;
+
+public class FileLogger implements Observer {
+ private final String filePath;
+
+ public FileLogger(String filePath) {
+ this.filePath = filePath;
+ }
+
+ @Override
+ public void update(String symbol, double price) {
+ try (FileWriter fw = new FileWriter(filePath, true)) {
+ fw.write(LocalDateTime.now() + " | " + symbol + " price: " + price + "\n");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/behavioral/Observer/observer/Observer.java b/src/main/java/behavioral/Observer/observer/Observer.java
new file mode 100644
index 0000000..268f1b4
--- /dev/null
+++ b/src/main/java/behavioral/Observer/observer/Observer.java
@@ -0,0 +1,5 @@
+package com.codencode.observer;
+
+public interface Observer {
+ void update(String symbol, double price);
+}
diff --git a/src/main/java/behavioral/Observer/subject/Stock.java b/src/main/java/behavioral/Observer/subject/Stock.java
new file mode 100644
index 0000000..ef5db1f
--- /dev/null
+++ b/src/main/java/behavioral/Observer/subject/Stock.java
@@ -0,0 +1,45 @@
+package com.codencode.subject;
+
+import com.codencode.observer.Observer;
+
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class Stock implements Subject{
+ private final String symbol;
+ private double price;
+ private final List observers = new CopyOnWriteArrayList<>();
+ private final Random random = new Random();
+
+ public Stock(String symbol, double initialPrice) {
+ this.symbol = symbol;
+ this.price = initialPrice;
+ }
+
+ @Override
+ public void attach(Observer o) { observers.add(o); }
+
+ @Override
+ public void detach(Observer o) { observers.remove(o); }
+
+ @Override
+ public void notifyObservers() {
+ for (Observer o : observers) {
+ o.update(symbol, price);
+ }
+ }
+
+ // Simulates price changes every few seconds
+ public void startPriceFeed() {
+ ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+ scheduler.scheduleAtFixedRate(() -> {
+ double change = (random.nextDouble() - 0.5) * 10; // +/-5 fluctuation
+ price = Math.round((price + change) * 100.0) / 100.0; // 2 decimals
+ notifyObservers();
+ }, 0, 5, TimeUnit.SECONDS);
+ }
+}
diff --git a/src/main/java/behavioral/Observer/subject/Subject.java b/src/main/java/behavioral/Observer/subject/Subject.java
new file mode 100644
index 0000000..9d0e713
--- /dev/null
+++ b/src/main/java/behavioral/Observer/subject/Subject.java
@@ -0,0 +1,9 @@
+package com.codencode.subject;
+
+import com.codencode.observer.Observer;
+
+public interface Subject {
+ void attach(Observer o);
+ void detach(Observer o);
+ void notifyObservers();
+}
diff --git a/src/main/java/behavioral/chainofresponsibility/CORDemo.java b/src/main/java/behavioral/chainofresponsibility/CORDemo.java
new file mode 100644
index 0000000..4ca6c34
--- /dev/null
+++ b/src/main/java/behavioral/chainofresponsibility/CORDemo.java
@@ -0,0 +1,50 @@
+package behavioral.chainofresponsibility;
+
+import behavioral.chainofresponsibility.dto.HttpRequest;
+import behavioral.chainofresponsibility.filter.*;
+
+public class CORDemo {
+ public static void main(String[] args) {
+ // Assemble security gateway infrastructure pipeline
+ BaseFilter pipelineGateway = new LoggingFilter();
+ pipelineGateway.setNext(new AuthenticationFilter())
+ .setNext(new AuthorizationFilter())
+ .setNext(new RateLimitFilter());
+
+ System.out.println("==================================================");
+ System.out.println("SCENARIO 1: Valid Admin Endpoint Request");
+ System.out.println("==================================================");
+ HttpRequest validRequest = new HttpRequest("/api/v1/admin/dashboard", "SECRET_TOKEN_XYZ123", "ADMIN_ROLE", 12);
+
+ if (pipelineGateway.doFilter(validRequest)) {
+ System.out.println("\nHTTP 200 OK: Routing request to core controller business engine logic.");
+ }
+
+ System.out.println("\n==================================================");
+ System.out.println("SCENARIO 2: Anonymous User Violating Authentication");
+ System.out.println("==================================================");
+ HttpRequest unauthenticatedRequest = new HttpRequest("/api/v1/user/profile", null, "GUEST", 1);
+
+ if (!pipelineGateway.doFilter(unauthenticatedRequest)) {
+ System.out.println("\nRequest failed security evaluation early at pipeline level.");
+ }
+
+ System.out.println("\n==================================================");
+ System.out.println("SCENARIO 3: Authenticated User Violating Authorization Roles");
+ System.out.println("==================================================");
+ HttpRequest unauthorizedRequest = new HttpRequest("/api/v1/admin/settings", "SECRET_TOKEN_ABC987", "STANDARD_USER_ROLE", 5);
+
+ if (!pipelineGateway.doFilter(unauthorizedRequest)) {
+ System.out.println("\nRequest failed security evaluation early at pipeline level.");
+ }
+
+ System.out.println("\n==================================================");
+ System.out.println("SCENARIO 4: Admin Triggering Rate Limiter Thresholds");
+ System.out.println("==================================================");
+ HttpRequest highTrafficRequest = new HttpRequest("/api/v1/admin/analytics", "SECRET_TOKEN_XYZ123", "ADMIN_ROLE", 150);
+
+ if (!pipelineGateway.doFilter(highTrafficRequest)) {
+ System.out.println("\nRequest failed security evaluation early at pipeline level.");
+ }
+ }
+}
diff --git a/src/main/java/behavioral/chainofresponsibility/dto/HttpRequest.java b/src/main/java/behavioral/chainofresponsibility/dto/HttpRequest.java
new file mode 100644
index 0000000..79391da
--- /dev/null
+++ b/src/main/java/behavioral/chainofresponsibility/dto/HttpRequest.java
@@ -0,0 +1,21 @@
+package behavioral.chainofresponsibility.dto;
+
+public class HttpRequest {
+ private final String path;
+ private final String authToken;
+ private final String userRole;
+ private final int requestCountInLastMinute;
+
+ public HttpRequest(String path, String authToken, String userRole, int requestCountInLastMinute) {
+ this.path = path;
+ this.authToken = authToken;
+ this.userRole = userRole;
+ this.requestCountInLastMinute = requestCountInLastMinute;
+ }
+
+ // Getters
+ public String getPath() { return path; }
+ public String getAuthToken() { return authToken; }
+ public String getUserRole() { return userRole; }
+ public int getRequestCountInLastMinute() { return requestCountInLastMinute; }
+}
diff --git a/src/main/java/behavioral/chainofresponsibility/filter/AuthenticationFilter.java b/src/main/java/behavioral/chainofresponsibility/filter/AuthenticationFilter.java
new file mode 100644
index 0000000..0fa01ed
--- /dev/null
+++ b/src/main/java/behavioral/chainofresponsibility/filter/AuthenticationFilter.java
@@ -0,0 +1,18 @@
+package behavioral.chainofresponsibility.filter;
+
+import behavioral.chainofresponsibility.dto.HttpRequest;
+
+public class AuthenticationFilter extends BaseFilter {
+ @Override
+ public boolean doFilter(HttpRequest request) {
+ System.out.println("[Filter 2: AuthN] Verifying security credentials token...");
+
+ if (request.getAuthToken() == null || !request.getAuthToken().startsWith("SECRET_TOKEN_")) {
+ System.err.println("HTTP 401 Unauthorized: Session token is missing or corrupted.");
+ return false; // Terminates request immediately
+ }
+
+ System.out.println("Identity identity verified successfully.");
+ return passToNext(request);
+ }
+}
diff --git a/src/main/java/behavioral/chainofresponsibility/filter/AuthorizationFilter.java b/src/main/java/behavioral/chainofresponsibility/filter/AuthorizationFilter.java
new file mode 100644
index 0000000..55b8a5a
--- /dev/null
+++ b/src/main/java/behavioral/chainofresponsibility/filter/AuthorizationFilter.java
@@ -0,0 +1,19 @@
+package behavioral.chainofresponsibility.filter;
+
+import behavioral.chainofresponsibility.dto.HttpRequest;
+
+public class AuthorizationFilter extends BaseFilter {
+ @Override
+ public boolean doFilter(HttpRequest request) {
+ System.out.println("[Filter 3: AuthZ] Verifying access permissions for path: " + request.getPath());
+
+ // Simulating protected resource administration check
+ if (request.getPath().contains("/admin") && !"ADMIN_ROLE".equalsIgnoreCase(request.getUserRole())) {
+ System.err.println("HTTP 403 Forbidden: Insufficient clearance levels for this role type.");
+ return false; // Terminates request immediately
+ }
+
+ System.out.println("Access permissions granted.");
+ return passToNext(request);
+ }
+}
diff --git a/src/main/java/behavioral/chainofresponsibility/filter/BaseFilter.java b/src/main/java/behavioral/chainofresponsibility/filter/BaseFilter.java
new file mode 100644
index 0000000..80b8a0f
--- /dev/null
+++ b/src/main/java/behavioral/chainofresponsibility/filter/BaseFilter.java
@@ -0,0 +1,32 @@
+package behavioral.chainofresponsibility.filter;
+
+import behavioral.chainofresponsibility.dto.HttpRequest;
+
+public abstract class BaseFilter {
+ private BaseFilter nextFilter;
+
+ /**
+ * Links filters sequentially.
+ * Returns the next filter reference to support fluent chaining.
+ */
+ public BaseFilter setNext(BaseFilter nextFilter) {
+ this.nextFilter = nextFilter;
+ return nextFilter;
+ }
+
+ /**
+ * Abstract method that contains specific filter processing logic.
+ * Returns true to continue down the chain, false to abort.
+ */
+ public abstract boolean doFilter(HttpRequest request);
+
+ /**
+ * Standard propagation helper to cleanly forward execution to the next node.
+ */
+ protected boolean passToNext(HttpRequest request) {
+ if (nextFilter == null) {
+ return true; // Reached end of pipeline processing safely
+ }
+ return nextFilter.doFilter(request);
+ }
+}
diff --git a/src/main/java/behavioral/chainofresponsibility/filter/LoggingFilter.java b/src/main/java/behavioral/chainofresponsibility/filter/LoggingFilter.java
new file mode 100644
index 0000000..d4f0adc
--- /dev/null
+++ b/src/main/java/behavioral/chainofresponsibility/filter/LoggingFilter.java
@@ -0,0 +1,12 @@
+package behavioral.chainofresponsibility.filter;
+
+import behavioral.chainofresponsibility.dto.HttpRequest;
+
+public class LoggingFilter extends BaseFilter {
+ @Override
+ public boolean doFilter(HttpRequest request) {
+ System.out.println("[Filter 1: Logger] Incoming request intercepted on path: " + request.getPath());
+ // Logging never breaks the chain, it just records and passes down
+ return passToNext(request);
+ }
+}
diff --git a/src/main/java/behavioral/chainofresponsibility/filter/RateLimitFilter.java b/src/main/java/behavioral/chainofresponsibility/filter/RateLimitFilter.java
new file mode 100644
index 0000000..e0653e3
--- /dev/null
+++ b/src/main/java/behavioral/chainofresponsibility/filter/RateLimitFilter.java
@@ -0,0 +1,20 @@
+package behavioral.chainofresponsibility.filter;
+
+import behavioral.chainofresponsibility.dto.HttpRequest;
+
+public class RateLimitFilter extends BaseFilter {
+ private static final int MAX_REQUESTS_PER_MINUTE = 60;
+
+ @Override
+ public boolean doFilter(HttpRequest request) {
+ System.out.println("[Filter 4: Throttling] Calculating throughput metric vectors...");
+
+ if (request.getRequestCountInLastMinute() > MAX_REQUESTS_PER_MINUTE) {
+ System.err.println("HTTP 429 Too Many Requests: Flood mitigation triggered. Request dropped.");
+ return false; // Terminates request immediately
+ }
+
+ System.out.println("Safe throughput threshold cleared.");
+ return passToNext(request);
+ }
+}
diff --git a/creational/FactoryMethod/README.md b/src/main/java/creational/FactoryMethod/README.md
similarity index 100%
rename from creational/FactoryMethod/README.md
rename to src/main/java/creational/FactoryMethod/README.md
diff --git a/src/main/java/creational/FactoryMethod/preffered/client/Main.java b/src/main/java/creational/FactoryMethod/preffered/client/Main.java
new file mode 100644
index 0000000..1b26b44
--- /dev/null
+++ b/src/main/java/creational/FactoryMethod/preffered/client/Main.java
@@ -0,0 +1,12 @@
+package creational.FactoryMethod.preffered.client;
+
+import creational.FactoryMethod.preffered.library.factory.SMSNotificationFactory;
+import creational.FactoryMethod.preffered.library.notification.Notification;
+
+public class Main {
+ public static void main(String[] args) {
+ Notification notification = new SMSNotificationFactory().createNotification();
+
+ notification.notifyUser();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/creational/FactoryMethod/preffered/library/factory/EmailNotificationFactory.java b/src/main/java/creational/FactoryMethod/preffered/library/factory/EmailNotificationFactory.java
new file mode 100644
index 0000000..c37ef97
--- /dev/null
+++ b/src/main/java/creational/FactoryMethod/preffered/library/factory/EmailNotificationFactory.java
@@ -0,0 +1,11 @@
+package creational.FactoryMethod.preffered.library.factory;
+
+import creational.FactoryMethod.preffered.library.notification.EmailNotification;
+import creational.FactoryMethod.preffered.library.notification.Notification;
+
+public class EmailNotificationFactory implements NotificationFactory{
+ @Override
+ public Notification createNotification() {
+ return new EmailNotification();
+ }
+}
diff --git a/src/main/java/creational/FactoryMethod/preffered/library/factory/NotificationFactory.java b/src/main/java/creational/FactoryMethod/preffered/library/factory/NotificationFactory.java
new file mode 100644
index 0000000..3abdfb3
--- /dev/null
+++ b/src/main/java/creational/FactoryMethod/preffered/library/factory/NotificationFactory.java
@@ -0,0 +1,7 @@
+package creational.FactoryMethod.preffered.library.factory;
+
+import creational.FactoryMethod.preffered.library.notification.Notification;
+
+public interface NotificationFactory {
+ public Notification createNotification();
+}
diff --git a/src/main/java/creational/FactoryMethod/preffered/library/factory/PushNotificationFactory.java b/src/main/java/creational/FactoryMethod/preffered/library/factory/PushNotificationFactory.java
new file mode 100644
index 0000000..d81064a
--- /dev/null
+++ b/src/main/java/creational/FactoryMethod/preffered/library/factory/PushNotificationFactory.java
@@ -0,0 +1,11 @@
+package creational.FactoryMethod.preffered.library.factory;
+
+import creational.FactoryMethod.preffered.library.notification.Notification;
+import creational.FactoryMethod.preffered.library.notification.PushNotification;
+
+public class PushNotificationFactory implements NotificationFactory{
+ @Override
+ public Notification createNotification() {
+ return new PushNotification();
+ }
+}
diff --git a/src/main/java/creational/FactoryMethod/preffered/library/factory/SMSNotificationFactory.java b/src/main/java/creational/FactoryMethod/preffered/library/factory/SMSNotificationFactory.java
new file mode 100644
index 0000000..8a093f9
--- /dev/null
+++ b/src/main/java/creational/FactoryMethod/preffered/library/factory/SMSNotificationFactory.java
@@ -0,0 +1,11 @@
+package creational.FactoryMethod.preffered.library.factory;
+
+import creational.FactoryMethod.preffered.library.notification.Notification;
+import creational.FactoryMethod.preffered.library.notification.SMSNotification;
+
+public class SMSNotificationFactory implements NotificationFactory{
+ @Override
+ public Notification createNotification() {
+ return new SMSNotification();
+ }
+}
diff --git a/creational/FactoryMethod/preffered/library/notification/EmailNotification.java b/src/main/java/creational/FactoryMethod/preffered/library/notification/EmailNotification.java
similarity index 72%
rename from creational/FactoryMethod/preffered/library/notification/EmailNotification.java
rename to src/main/java/creational/FactoryMethod/preffered/library/notification/EmailNotification.java
index 84a184d..f74fe30 100644
--- a/creational/FactoryMethod/preffered/library/notification/EmailNotification.java
+++ b/src/main/java/creational/FactoryMethod/preffered/library/notification/EmailNotification.java
@@ -1,4 +1,4 @@
-package com.codencode.preffered.library.notification;
+package creational.FactoryMethod.preffered.library.notification;
public class EmailNotification implements Notification{
@Override
diff --git a/src/main/java/creational/FactoryMethod/preffered/library/notification/Notification.java b/src/main/java/creational/FactoryMethod/preffered/library/notification/Notification.java
new file mode 100644
index 0000000..013de83
--- /dev/null
+++ b/src/main/java/creational/FactoryMethod/preffered/library/notification/Notification.java
@@ -0,0 +1,5 @@
+package creational.FactoryMethod.preffered.library.notification;
+
+public interface Notification {
+ void notifyUser();
+}
diff --git a/creational/FactoryMethod/preffered/library/notification/PushNotification.java b/src/main/java/creational/FactoryMethod/preffered/library/notification/PushNotification.java
similarity index 72%
rename from creational/FactoryMethod/preffered/library/notification/PushNotification.java
rename to src/main/java/creational/FactoryMethod/preffered/library/notification/PushNotification.java
index feed386..da5e2f9 100644
--- a/creational/FactoryMethod/preffered/library/notification/PushNotification.java
+++ b/src/main/java/creational/FactoryMethod/preffered/library/notification/PushNotification.java
@@ -1,4 +1,4 @@
-package com.codencode.preffered.library.notification;
+package creational.FactoryMethod.preffered.library.notification;
public class PushNotification implements Notification{
@Override
diff --git a/creational/FactoryMethod/preffered/library/notification/SMSNotification.java b/src/main/java/creational/FactoryMethod/preffered/library/notification/SMSNotification.java
similarity index 72%
rename from creational/FactoryMethod/preffered/library/notification/SMSNotification.java
rename to src/main/java/creational/FactoryMethod/preffered/library/notification/SMSNotification.java
index 60e1f07..e693001 100644
--- a/creational/FactoryMethod/preffered/library/notification/SMSNotification.java
+++ b/src/main/java/creational/FactoryMethod/preffered/library/notification/SMSNotification.java
@@ -1,4 +1,4 @@
-package com.codencode.preffered.library.notification;
+package creational.FactoryMethod.preffered.library.notification;
public class SMSNotification implements Notification{
@Override
diff --git a/src/main/java/creational/FactoryMethod/simple/client/Main.java b/src/main/java/creational/FactoryMethod/simple/client/Main.java
new file mode 100644
index 0000000..29215de
--- /dev/null
+++ b/src/main/java/creational/FactoryMethod/simple/client/Main.java
@@ -0,0 +1,13 @@
+package creational.FactoryMethod.simple.client;
+
+import creational.FactoryMethod.simple.library.CompilerFactory;
+import creational.FactoryMethod.simple.library.compiler.Compiler;
+import creational.FactoryMethod.simple.library.compiler.CompilerType;
+
+public class Main {
+ public static void main(String[] args) {
+ Compiler compiler = CompilerFactory.getCompiler(CompilerType.JAVA);
+
+ System.out.println(compiler.compile("c"));
+ }
+}
\ No newline at end of file
diff --git a/creational/FactoryMethod/simple/library/CompilerFactory.java b/src/main/java/creational/FactoryMethod/simple/library/CompilerFactory.java
similarity index 73%
rename from creational/FactoryMethod/simple/library/CompilerFactory.java
rename to src/main/java/creational/FactoryMethod/simple/library/CompilerFactory.java
index 5510a6a..c585846 100644
--- a/creational/FactoryMethod/simple/library/CompilerFactory.java
+++ b/src/main/java/creational/FactoryMethod/simple/library/CompilerFactory.java
@@ -1,7 +1,8 @@
-package com.codencode.simple.library;
+package creational.FactoryMethod.simple.library;
-import com.codencode.simple.library.compiler.*;
-import com.codencode.simple.library.compiler.Compiler;
+
+import creational.FactoryMethod.simple.library.compiler.*;
+import creational.FactoryMethod.simple.library.compiler.Compiler;
public class CompilerFactory {
public static Compiler getCompiler(CompilerType type) {
diff --git a/creational/FactoryMethod/simple/library/compiler/Compiler.java b/src/main/java/creational/FactoryMethod/simple/library/compiler/Compiler.java
similarity index 59%
rename from creational/FactoryMethod/simple/library/compiler/Compiler.java
rename to src/main/java/creational/FactoryMethod/simple/library/compiler/Compiler.java
index c8ff83c..83fbb1e 100644
--- a/creational/FactoryMethod/simple/library/compiler/Compiler.java
+++ b/src/main/java/creational/FactoryMethod/simple/library/compiler/Compiler.java
@@ -1,4 +1,4 @@
-package com.codencode.simple.library.compiler;
+package creational.FactoryMethod.simple.library.compiler;
public abstract class Compiler {
public abstract String compile(String code);
diff --git a/creational/FactoryMethod/simple/library/compiler/CompilerType.java b/src/main/java/creational/FactoryMethod/simple/library/compiler/CompilerType.java
similarity index 50%
rename from creational/FactoryMethod/simple/library/compiler/CompilerType.java
rename to src/main/java/creational/FactoryMethod/simple/library/compiler/CompilerType.java
index 5168d67..5061a92 100644
--- a/creational/FactoryMethod/simple/library/compiler/CompilerType.java
+++ b/src/main/java/creational/FactoryMethod/simple/library/compiler/CompilerType.java
@@ -1,4 +1,4 @@
-package com.codencode.simple.library.compiler;
+package creational.FactoryMethod.simple.library.compiler;
public enum CompilerType {
CPP,
diff --git a/creational/FactoryMethod/simple/library/compiler/CppCompiler.java b/src/main/java/creational/FactoryMethod/simple/library/compiler/CppCompiler.java
similarity index 74%
rename from creational/FactoryMethod/simple/library/compiler/CppCompiler.java
rename to src/main/java/creational/FactoryMethod/simple/library/compiler/CppCompiler.java
index 70e6082..530764f 100644
--- a/creational/FactoryMethod/simple/library/compiler/CppCompiler.java
+++ b/src/main/java/creational/FactoryMethod/simple/library/compiler/CppCompiler.java
@@ -1,4 +1,5 @@
-package com.codencode.simple.library.compiler;
+package creational.FactoryMethod.simple.library.compiler;
+
public class CppCompiler extends Compiler {
diff --git a/creational/FactoryMethod/simple/library/compiler/JavaCompiler.java b/src/main/java/creational/FactoryMethod/simple/library/compiler/JavaCompiler.java
similarity index 75%
rename from creational/FactoryMethod/simple/library/compiler/JavaCompiler.java
rename to src/main/java/creational/FactoryMethod/simple/library/compiler/JavaCompiler.java
index 493cfc7..a9388e8 100644
--- a/creational/FactoryMethod/simple/library/compiler/JavaCompiler.java
+++ b/src/main/java/creational/FactoryMethod/simple/library/compiler/JavaCompiler.java
@@ -1,4 +1,4 @@
-package com.codencode.simple.library.compiler;
+package creational.FactoryMethod.simple.library.compiler;
public class JavaCompiler extends Compiler {
@Override
diff --git a/creational/FactoryMethod/simple/library/compiler/PythonCompiler.java b/src/main/java/creational/FactoryMethod/simple/library/compiler/PythonCompiler.java
similarity index 75%
rename from creational/FactoryMethod/simple/library/compiler/PythonCompiler.java
rename to src/main/java/creational/FactoryMethod/simple/library/compiler/PythonCompiler.java
index cf2bdd8..caf124c 100644
--- a/creational/FactoryMethod/simple/library/compiler/PythonCompiler.java
+++ b/src/main/java/creational/FactoryMethod/simple/library/compiler/PythonCompiler.java
@@ -1,4 +1,5 @@
-package com.codencode.simple.library.compiler;
+package creational.FactoryMethod.simple.library.compiler;
+
public class PythonCompiler extends Compiler {
@Override
diff --git a/src/main/java/structural/Bridge/BridgeDemo.java b/src/main/java/structural/Bridge/BridgeDemo.java
new file mode 100644
index 0000000..a3c1a96
--- /dev/null
+++ b/src/main/java/structural/Bridge/BridgeDemo.java
@@ -0,0 +1,12 @@
+package com.codencode;
+
+import com.codencode.payment.CreditCardPayment;
+import com.codencode.payment.Payment;
+import com.codencode.payment.gateway.JuspayPaymentGateway;
+
+public class BridgeDemo {
+ public static void main(String[] args) {
+ Payment payment = new CreditCardPayment(new JuspayPaymentGateway());
+ payment.processPayment(500);
+ }
+}
diff --git a/src/main/java/structural/Bridge/payment/CreditCardPayment.java b/src/main/java/structural/Bridge/payment/CreditCardPayment.java
new file mode 100644
index 0000000..8485424
--- /dev/null
+++ b/src/main/java/structural/Bridge/payment/CreditCardPayment.java
@@ -0,0 +1,16 @@
+package com.codencode.payment;
+
+import com.codencode.payment.gateway.Gateway;
+
+public class CreditCardPayment extends Payment {
+ public CreditCardPayment(Gateway gateway) {
+ super(gateway);
+ }
+
+ @Override
+ public void processPayment(double amount) {
+ System.out.println("Paying through credit card");
+ gateway.processPayment(amount);
+ }
+
+}
diff --git a/src/main/java/structural/Bridge/payment/Payment.java b/src/main/java/structural/Bridge/payment/Payment.java
new file mode 100644
index 0000000..3d39f61
--- /dev/null
+++ b/src/main/java/structural/Bridge/payment/Payment.java
@@ -0,0 +1,13 @@
+package com.codencode.payment;
+
+import com.codencode.payment.gateway.Gateway;
+
+public abstract class Payment {
+ protected Gateway gateway;
+
+ public Payment(Gateway gateway) {
+ this.gateway = gateway;
+ }
+
+ public abstract void processPayment(double amount);
+}
diff --git a/src/main/java/structural/Bridge/payment/UpiPayment.java b/src/main/java/structural/Bridge/payment/UpiPayment.java
new file mode 100644
index 0000000..7ed03ac
--- /dev/null
+++ b/src/main/java/structural/Bridge/payment/UpiPayment.java
@@ -0,0 +1,15 @@
+package com.codencode.payment;
+
+import com.codencode.payment.gateway.Gateway;
+
+public class UpiPayment extends Payment{
+ public UpiPayment(Gateway gateway) {
+ super(gateway);
+ }
+
+ @Override
+ public void processPayment(double amount) {
+ System.out.println("Paying through UPI");
+ gateway.processPayment(amount);
+ }
+}
diff --git a/src/main/java/structural/Bridge/payment/gateway/Gateway.java b/src/main/java/structural/Bridge/payment/gateway/Gateway.java
new file mode 100644
index 0000000..a390395
--- /dev/null
+++ b/src/main/java/structural/Bridge/payment/gateway/Gateway.java
@@ -0,0 +1,5 @@
+package com.codencode.payment.gateway;
+
+public interface Gateway {
+ void processPayment(double amount);
+}
diff --git a/src/main/java/structural/Bridge/payment/gateway/JuspayPaymentGateway.java b/src/main/java/structural/Bridge/payment/gateway/JuspayPaymentGateway.java
new file mode 100644
index 0000000..8dff70a
--- /dev/null
+++ b/src/main/java/structural/Bridge/payment/gateway/JuspayPaymentGateway.java
@@ -0,0 +1,9 @@
+package com.codencode.payment.gateway;
+
+public class JuspayPaymentGateway implements Gateway{
+ @Override
+ public void processPayment(double amount) {
+ System.out.println("Juspay Payment Gateway");
+ System.out.println("Processing payment of amount: " + amount);
+ }
+}
diff --git a/src/main/java/structural/Bridge/payment/gateway/PaypalPaymentGateway.java b/src/main/java/structural/Bridge/payment/gateway/PaypalPaymentGateway.java
new file mode 100644
index 0000000..0dfc357
--- /dev/null
+++ b/src/main/java/structural/Bridge/payment/gateway/PaypalPaymentGateway.java
@@ -0,0 +1,9 @@
+package com.codencode.payment.gateway;
+
+public class PaypalPaymentGateway implements Gateway {
+ @Override
+ public void processPayment(double amount) {
+ System.out.println("Paypal Payment Gateway");
+ System.out.println("Processing payment of amount: " + amount);
+ }
+}
diff --git a/src/main/java/structural/Bridge/payment/gateway/SbiPaymentGateway.java b/src/main/java/structural/Bridge/payment/gateway/SbiPaymentGateway.java
new file mode 100644
index 0000000..acbc8ea
--- /dev/null
+++ b/src/main/java/structural/Bridge/payment/gateway/SbiPaymentGateway.java
@@ -0,0 +1,9 @@
+package com.codencode.payment.gateway;
+
+public class SbiPaymentGateway implements Gateway {
+ @Override
+ public void processPayment(double amount) {
+ System.out.println("SBI Payment Gateway");
+ System.out.println("Processing payment of amount: " + amount);
+ }
+}
diff --git a/src/main/java/structural/adapter/AdapterDemo.java b/src/main/java/structural/adapter/AdapterDemo.java
new file mode 100644
index 0000000..6fd8a57
--- /dev/null
+++ b/src/main/java/structural/adapter/AdapterDemo.java
@@ -0,0 +1,8 @@
+package structural.adapter;
+
+public class AdapterDemo {
+ public static void main(String[] args) {
+ Logger logger = new FileLoggerAdapter(new FileLogger());
+ logger.log("Hello World again.");
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/structural/adapter/ConsoleLogger.java b/src/main/java/structural/adapter/ConsoleLogger.java
new file mode 100644
index 0000000..603ea3d
--- /dev/null
+++ b/src/main/java/structural/adapter/ConsoleLogger.java
@@ -0,0 +1,8 @@
+package structural.adapter;
+
+public class ConsoleLogger implements Logger {
+ @Override
+ public void log(String message) {
+ System.out.println("Console Log: " + message);
+ }
+}
diff --git a/src/main/java/structural/adapter/FileLogger.java b/src/main/java/structural/adapter/FileLogger.java
new file mode 100644
index 0000000..651f3a0
--- /dev/null
+++ b/src/main/java/structural/adapter/FileLogger.java
@@ -0,0 +1,14 @@
+package structural.adapter;
+
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class FileLogger {
+ public void writeToFile(String message) {
+ try (FileWriter writer = new FileWriter("logs.txt", true)) {
+ writer.write("File Log: " + message + "\n");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/main/java/structural/adapter/FileLoggerAdapter.java b/src/main/java/structural/adapter/FileLoggerAdapter.java
new file mode 100644
index 0000000..521915d
--- /dev/null
+++ b/src/main/java/structural/adapter/FileLoggerAdapter.java
@@ -0,0 +1,14 @@
+package structural.adapter;
+
+public class FileLoggerAdapter implements Logger {
+ private final FileLogger fileLogger;
+
+ public FileLoggerAdapter(FileLogger fileLogger) {
+ this.fileLogger = fileLogger;
+ }
+
+ @Override
+ public void log(String message) {
+ fileLogger.writeToFile(message);
+ }
+}
diff --git a/src/main/java/structural/adapter/Logger.java b/src/main/java/structural/adapter/Logger.java
new file mode 100644
index 0000000..8cefcca
--- /dev/null
+++ b/src/main/java/structural/adapter/Logger.java
@@ -0,0 +1,5 @@
+package structural.adapter;
+
+public interface Logger {
+ void log(String message);
+}
\ No newline at end of file
diff --git a/src/main/java/structural/decorator/DecoratorDemo.java b/src/main/java/structural/decorator/DecoratorDemo.java
new file mode 100644
index 0000000..7bbf99a
--- /dev/null
+++ b/src/main/java/structural/decorator/DecoratorDemo.java
@@ -0,0 +1,15 @@
+package com.codencode;
+
+
+import com.codencode.compiler.Compiler;
+import com.codencode.compiler.CppCompiler;
+import com.codencode.logger.AroundLogger;
+
+public class DecoratorDemo {
+ public static void main(String[] args) {
+ Compiler compiler = new CppCompiler();
+
+ compiler = new AroundLogger(compiler);
+ compiler.compile("Hello World");
+ }
+}
diff --git a/src/main/java/structural/decorator/compiler/Compiler.java b/src/main/java/structural/decorator/compiler/Compiler.java
new file mode 100644
index 0000000..9bb24d5
--- /dev/null
+++ b/src/main/java/structural/decorator/compiler/Compiler.java
@@ -0,0 +1,5 @@
+package com.codencode.compiler;
+
+public interface Compiler {
+ void compile(String code);
+}
diff --git a/src/main/java/structural/decorator/compiler/CppCompiler.java b/src/main/java/structural/decorator/compiler/CppCompiler.java
new file mode 100644
index 0000000..21cb72b
--- /dev/null
+++ b/src/main/java/structural/decorator/compiler/CppCompiler.java
@@ -0,0 +1,9 @@
+package com.codencode.compiler;
+
+public class CppCompiler implements Compiler {
+ @Override
+ public void compile(String code) {
+ System.out.println("Compiler: CPP");
+ System.out.println("Compiling Code\n" + code);
+ }
+}
diff --git a/src/main/java/structural/decorator/compiler/JavaCompiler.java b/src/main/java/structural/decorator/compiler/JavaCompiler.java
new file mode 100644
index 0000000..1604d9b
--- /dev/null
+++ b/src/main/java/structural/decorator/compiler/JavaCompiler.java
@@ -0,0 +1,9 @@
+package com.codencode.compiler;
+
+public class JavaCompiler implements Compiler {
+ @Override
+ public void compile(String code) {
+ System.out.println("Compiler: Java");
+ System.out.println("Compiling Code\n" + code);
+ }
+}
diff --git a/src/main/java/structural/decorator/logger/AfterLogger.java b/src/main/java/structural/decorator/logger/AfterLogger.java
new file mode 100644
index 0000000..fec31f8
--- /dev/null
+++ b/src/main/java/structural/decorator/logger/AfterLogger.java
@@ -0,0 +1,15 @@
+package com.codencode.logger;
+
+import com.codencode.compiler.Compiler;
+
+public class AfterLogger extends Logger {
+ public AfterLogger(Compiler compiler) {
+ super(compiler);
+ }
+
+ @Override
+ public void compile(String code) {
+ compiler.compile(code);
+ System.out.println("[After Logger] Code compilation complete.");
+ }
+}
diff --git a/src/main/java/structural/decorator/logger/AroundLogger.java b/src/main/java/structural/decorator/logger/AroundLogger.java
new file mode 100644
index 0000000..a394a09
--- /dev/null
+++ b/src/main/java/structural/decorator/logger/AroundLogger.java
@@ -0,0 +1,16 @@
+package com.codencode.logger;
+
+import com.codencode.compiler.Compiler;
+
+public class AroundLogger extends Logger {
+ public AroundLogger(Compiler compiler) {
+ super(compiler);
+ }
+
+ @Override
+ public void compile(String code) {
+ System.out.println("[Around Logger] About to compile code.");
+ compiler.compile(code);
+ System.out.println("[Around Logger] Code compilation complete.");
+ }
+}
diff --git a/src/main/java/structural/decorator/logger/BeforeLogger.java b/src/main/java/structural/decorator/logger/BeforeLogger.java
new file mode 100644
index 0000000..77e7725
--- /dev/null
+++ b/src/main/java/structural/decorator/logger/BeforeLogger.java
@@ -0,0 +1,15 @@
+package com.codencode.logger;
+
+import com.codencode.compiler.Compiler;
+
+public class BeforeLogger extends Logger {
+ public BeforeLogger(Compiler compiler) {
+ super(compiler);
+ }
+
+ @Override
+ public void compile(String code) {
+ System.out.println("[Before Logger] About to compile code.");
+ compiler.compile(code);
+ }
+}
diff --git a/src/main/java/structural/decorator/logger/Logger.java b/src/main/java/structural/decorator/logger/Logger.java
new file mode 100644
index 0000000..548430b
--- /dev/null
+++ b/src/main/java/structural/decorator/logger/Logger.java
@@ -0,0 +1,11 @@
+package com.codencode.logger;
+
+import com.codencode.compiler.Compiler;
+
+public abstract class Logger implements Compiler {
+ protected Compiler compiler;
+
+ public Logger(Compiler compiler) {
+ this.compiler = compiler;
+ }
+}
diff --git a/src/main/java/structural/proxy/README.md b/src/main/java/structural/proxy/README.md
new file mode 100644
index 0000000..a3c6d71
--- /dev/null
+++ b/src/main/java/structural/proxy/README.md
@@ -0,0 +1,21 @@
+# Proxy Design Pattern
+
+
+The **Proxy Pattern** is a structural design pattern that provides a surrogate or placeholder for another object to control
+access to it. It is used when you want to add an extra layer of control over how and when an object is accessed or
+manipulated. The proxy acts as an intermediary between the client and the real object, allowing the proxy to perform
+additional tasks before or after the request reaches the real object.
+
+## Lecture & Important links
+
+- **Lecture Link** - [L07 - Proxy Design Pattern](https://youtu.be/t-WDABdUjy8)
+- **Complete Playlist** - [Design Patterns](https://www.youtube.com/playlist?list=PL5DyztRVgtRUqnoWYVAFC1honDiDpdKOX)
+- **Other Courses** - [CodeNCode @ YT](https://www.youtube.com/@codencode)
+
+
+
+## About the implementation
+Proxy Design Pattern is implemented using three different types.
+1. **protection_proxy**: Controls access to the real object based on access rights or permissions.
+2. **smart_proxy**: Adds additional behavior when the real object is accessed, such as logging, caching, or reference counting.
+3. **virtual_proxy**: Delays the creation and initialization of expensive objects until they are actually needed (lazy initialization).
diff --git a/src/main/java/structural/proxy/protection_proxy/BankAccount.java b/src/main/java/structural/proxy/protection_proxy/BankAccount.java
new file mode 100644
index 0000000..5c30a36
--- /dev/null
+++ b/src/main/java/structural/proxy/protection_proxy/BankAccount.java
@@ -0,0 +1,7 @@
+package structural.proxy.protection_proxy;
+
+public interface BankAccount {
+ void deposit(double amount);
+ void withdraw(double amount);
+ double getBalance();
+}
diff --git a/src/main/java/structural/proxy/protection_proxy/Main.java b/src/main/java/structural/proxy/protection_proxy/Main.java
new file mode 100644
index 0000000..8bc1679
--- /dev/null
+++ b/src/main/java/structural/proxy/protection_proxy/Main.java
@@ -0,0 +1,35 @@
+package structural.proxy.protection_proxy;
+
+public class Main {
+ public static void main(String[] args) {
+ // Create a proxy for a bank account with ADMIN access
+ BankAccount adminAccount = new ProxyBankAccount(1000, "ADMIN");
+
+ // Perform operations as ADMIN
+ System.out.println("Admin operations:");
+ adminAccount.deposit(500);
+ adminAccount.withdraw(200);
+ System.out.println("Admin balance: $" + adminAccount.getBalance());
+
+ // Create a proxy for a bank account with USER access
+ BankAccount userAccount = new ProxyBankAccount(1000, "USER");
+
+ // Perform operations as USER (access will be denied)
+ System.out.println("\nUser operations:");
+ try {
+ userAccount.deposit(300);
+ } catch (SecurityException e) {
+ System.out.println(e.getMessage());
+ }
+ try {
+ userAccount.withdraw(100);
+ } catch (SecurityException e) {
+ System.out.println(e.getMessage());
+ }
+ try {
+ System.out.println("User balance: $" + userAccount.getBalance());
+ } catch (SecurityException e) {
+ System.out.println(e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/structural/proxy/protection_proxy/ProxyBankAccount.java b/src/main/java/structural/proxy/protection_proxy/ProxyBankAccount.java
new file mode 100644
index 0000000..d6fe93a
--- /dev/null
+++ b/src/main/java/structural/proxy/protection_proxy/ProxyBankAccount.java
@@ -0,0 +1,54 @@
+package structural.proxy.protection_proxy;
+
+class ProxyBankAccount implements BankAccount {
+ private RealBankAccount realBankAccount;
+ private String userRole;
+ private double initialBalance;
+
+ public ProxyBankAccount(double initialBalance, String userRole) {
+ this.initialBalance = initialBalance;
+ this.userRole = userRole;
+ }
+
+ private void checkAccess() {
+ if (!userRole.equals("ADMIN")) {
+ throw new SecurityException("Access denied! You do not have permission to perform this operation.");
+ }
+ }
+
+ private void logOperation(String operation, double amount) {
+ System.out.println("Log: User with role '" + userRole + "' performed '" + operation + "' of $" + amount);
+ }
+
+ @Override
+ public void deposit(double amount) {
+ checkAccess(); // Check if the user has permission
+ if (realBankAccount == null) {
+ realBankAccount = new RealBankAccount(initialBalance); // Lazy initialization
+ }
+ realBankAccount.deposit(amount);
+ logOperation("deposit", amount); // Log the operation
+ }
+
+ @Override
+ public void withdraw(double amount) {
+ checkAccess(); // Check if the user has permission
+ if (realBankAccount == null) {
+ realBankAccount = new RealBankAccount(initialBalance); // Lazy initialization
+ }
+ realBankAccount.withdraw(amount);
+ logOperation("withdraw", amount); // Log the operation
+ }
+
+ @Override
+ public double getBalance() {
+ checkAccess(); // Check if the user has permission
+ if (realBankAccount == null) {
+ realBankAccount = new RealBankAccount(initialBalance); // Lazy initialization
+ }
+ double balance = realBankAccount.getBalance();
+ logOperation("getBalance", balance); // Log the operation
+ return balance;
+ }
+}
+
diff --git a/src/main/java/structural/proxy/protection_proxy/RealBankAccount.java b/src/main/java/structural/proxy/protection_proxy/RealBankAccount.java
new file mode 100644
index 0000000..ffbd437
--- /dev/null
+++ b/src/main/java/structural/proxy/protection_proxy/RealBankAccount.java
@@ -0,0 +1,30 @@
+package structural.proxy.protection_proxy;
+
+class RealBankAccount implements BankAccount {
+ private double balance;
+
+ public RealBankAccount(double initialBalance) {
+ this.balance = initialBalance;
+ }
+
+ @Override
+ public void deposit(double amount) {
+ balance += amount;
+ System.out.println("Deposited: $" + amount);
+ }
+
+ @Override
+ public void withdraw(double amount) {
+ if (balance >= amount) {
+ balance -= amount;
+ System.out.println("Withdrawn: $" + amount);
+ } else {
+ System.out.println("Insufficient balance to withdraw: $" + amount);
+ }
+ }
+
+ @Override
+ public double getBalance() {
+ return balance;
+ }
+}
diff --git a/src/main/java/structural/proxy/smart_proxy/MathService.java b/src/main/java/structural/proxy/smart_proxy/MathService.java
new file mode 100644
index 0000000..4fcb4b6
--- /dev/null
+++ b/src/main/java/structural/proxy/smart_proxy/MathService.java
@@ -0,0 +1,5 @@
+package structural.proxy.smart_proxy;
+
+interface MathService {
+ long computeFactorial(int number);
+}
\ No newline at end of file
diff --git a/src/main/java/structural/proxy/smart_proxy/RealMathService.java b/src/main/java/structural/proxy/smart_proxy/RealMathService.java
new file mode 100644
index 0000000..9543508
--- /dev/null
+++ b/src/main/java/structural/proxy/smart_proxy/RealMathService.java
@@ -0,0 +1,16 @@
+package structural.proxy.smart_proxy;
+
+class RealMathService implements MathService {
+ @Override
+ public long computeFactorial(int number) {
+ if (number < 0) {
+ throw new IllegalArgumentException("Number must be non-negative.");
+ }
+ long result = 1;
+ for (int i = 2; i <= number; i++) {
+ result *= i;
+ }
+ System.out.println("Computed factorial of " + number + ": " + result);
+ return result;
+ }
+}
diff --git a/src/main/java/structural/proxy/smart_proxy/SmartMathServiceProxy.java b/src/main/java/structural/proxy/smart_proxy/SmartMathServiceProxy.java
new file mode 100644
index 0000000..8443d92
--- /dev/null
+++ b/src/main/java/structural/proxy/smart_proxy/SmartMathServiceProxy.java
@@ -0,0 +1,30 @@
+package structural.proxy.smart_proxy;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class SmartMathServiceProxy implements MathService {
+ private final RealMathService realMathService;
+ private final Map cache; // Cache to store computed factorials
+
+ public SmartMathServiceProxy() {
+ this.realMathService = new RealMathService();
+ this.cache = new HashMap<>();
+ }
+
+ @Override
+ public long computeFactorial(int number) {
+ // Check if the result is already in the cache
+ if (cache.containsKey(number)) {
+ System.out.println("Returning cached result for " + number + ": " + cache.get(number));
+ return cache.get(number);
+ }
+
+ // Compute the factorial using the real object
+ long result = realMathService.computeFactorial(number);
+
+ // Cache the result for future use
+ cache.put(number, result);
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/structural/proxy/smart_proxy/SmartProxyDemo.java b/src/main/java/structural/proxy/smart_proxy/SmartProxyDemo.java
new file mode 100644
index 0000000..ab49a86
--- /dev/null
+++ b/src/main/java/structural/proxy/smart_proxy/SmartProxyDemo.java
@@ -0,0 +1,23 @@
+package structural.proxy.smart_proxy;
+
+public class SmartProxyDemo {
+ public static void main(String[] args) {
+ // Create the smart proxy
+ MathService mathService = new SmartMathServiceProxy();
+
+ // First call (computes and caches the result)
+ System.out.println("First call:");
+ long result1 = mathService.computeFactorial(5); // Computes and caches
+ System.out.println("Result: " + result1);
+
+ // Second call (returns cached result)
+ System.out.println("\nSecond call:");
+ long result2 = mathService.computeFactorial(5); // Returns cached result
+ System.out.println("Result: " + result2);
+
+ // Third call (computes and caches a new result)
+ System.out.println("\nThird call:");
+ long result3 = mathService.computeFactorial(10); // Computes and caches
+ System.out.println("Result: " + result3);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/structural/proxy/virtual_proxy/Image.java b/src/main/java/structural/proxy/virtual_proxy/Image.java
new file mode 100644
index 0000000..15c1e0b
--- /dev/null
+++ b/src/main/java/structural/proxy/virtual_proxy/Image.java
@@ -0,0 +1,5 @@
+package structural.proxy.virtual_proxy;
+
+public interface Image {
+ void display();
+}
diff --git a/src/main/java/structural/proxy/virtual_proxy/ProxyImage.java b/src/main/java/structural/proxy/virtual_proxy/ProxyImage.java
new file mode 100644
index 0000000..2272949
--- /dev/null
+++ b/src/main/java/structural/proxy/virtual_proxy/ProxyImage.java
@@ -0,0 +1,19 @@
+package structural.proxy.virtual_proxy;
+
+class ProxyImage implements Image {
+ private final String filename;
+ private RealImage realImage; // Reference to the real object
+
+ public ProxyImage(String filename) {
+ this.filename = filename;
+ }
+
+ @Override
+ public void display() {
+ // Lazy initialization: Create the real object only when needed
+ if (realImage == null) {
+ realImage = new RealImage(filename);
+ }
+ realImage.display();
+ }
+}
diff --git a/src/main/java/structural/proxy/virtual_proxy/RealImage.java b/src/main/java/structural/proxy/virtual_proxy/RealImage.java
new file mode 100644
index 0000000..e463b67
--- /dev/null
+++ b/src/main/java/structural/proxy/virtual_proxy/RealImage.java
@@ -0,0 +1,19 @@
+package structural.proxy.virtual_proxy;
+
+class RealImage implements Image {
+ private final String filename;
+
+ public RealImage(String filename) {
+ this.filename = filename;
+ loadFromDisk(); // Simulate loading the image from disk
+ }
+
+ private void loadFromDisk() {
+ System.out.println("Loading high-resolution image: " + filename);
+ }
+
+ @Override
+ public void display() {
+ System.out.println("Displaying image: " + filename);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/structural/proxy/virtual_proxy/VirtualProxyDemo.java b/src/main/java/structural/proxy/virtual_proxy/VirtualProxyDemo.java
new file mode 100644
index 0000000..04bce2d
--- /dev/null
+++ b/src/main/java/structural/proxy/virtual_proxy/VirtualProxyDemo.java
@@ -0,0 +1,17 @@
+package structural.proxy.virtual_proxy;
+
+public class VirtualProxyDemo {
+ public static void main(String[] args) {
+ // Create a virtual proxy for a high-resolution image
+ Image image = new ProxyImage("example.jpg");
+
+ // Image is not loaded yet
+ System.out.println("Image will be loaded only when display() is called.");
+
+ // Image is loaded and displayed
+ image.display();
+
+ // Image is already loaded, so it won't load again
+ image.display();
+ }
+}