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(); + } +}