diff --git a/01-creational/abstract-factory/Application.java b/01-creational/abstract-factory/Application.java new file mode 100644 index 0000000..9fb136f --- /dev/null +++ b/01-creational/abstract-factory/Application.java @@ -0,0 +1,21 @@ +package abstractfactory; + +/** Client - uses the factory without knowing concrete classes */ +public class Application { + private final Button button; + private final Checkbox checkbox; + + public Application(GUIFactory factory) { + button = factory.createButton(); + checkbox = factory.createCheckbox(); + } + + public void render() { + button.render(); + checkbox.render(); + } + + public void simulateClick() { + button.onClick(); + } +} diff --git a/01-creational/abstract-factory/Button.java b/01-creational/abstract-factory/Button.java new file mode 100644 index 0000000..4b7220e --- /dev/null +++ b/01-creational/abstract-factory/Button.java @@ -0,0 +1,6 @@ +package abstractfactory; + +public interface Button { + void render(); + void onClick(); +} diff --git a/01-creational/abstract-factory/Checkbox.java b/01-creational/abstract-factory/Checkbox.java new file mode 100644 index 0000000..4dc26fc --- /dev/null +++ b/01-creational/abstract-factory/Checkbox.java @@ -0,0 +1,5 @@ +package abstractfactory; + +public interface Checkbox { + void render(); +} diff --git a/01-creational/abstract-factory/GUIFactory.java b/01-creational/abstract-factory/GUIFactory.java new file mode 100644 index 0000000..96b8f58 --- /dev/null +++ b/01-creational/abstract-factory/GUIFactory.java @@ -0,0 +1,7 @@ +package abstractfactory; + +/** Abstract Factory - creates families of related UI components */ +public interface GUIFactory { + Button createButton(); + Checkbox createCheckbox(); +} diff --git a/01-creational/abstract-factory/MacButton.java b/01-creational/abstract-factory/MacButton.java new file mode 100644 index 0000000..e814831 --- /dev/null +++ b/01-creational/abstract-factory/MacButton.java @@ -0,0 +1,6 @@ +package abstractfactory; + +public class MacButton implements Button { + @Override public void render() { System.out.println("[Mac] Rendering button with rounded corners"); } + @Override public void onClick() { System.out.println("[Mac] Button clicked - glow animation"); } +} diff --git a/01-creational/abstract-factory/MacCheckbox.java b/01-creational/abstract-factory/MacCheckbox.java new file mode 100644 index 0000000..1f131a4 --- /dev/null +++ b/01-creational/abstract-factory/MacCheckbox.java @@ -0,0 +1,5 @@ +package abstractfactory; + +public class MacCheckbox implements Checkbox { + @Override public void render() { System.out.println("[Mac] Rendering checkbox with rounded tick box"); } +} diff --git a/01-creational/abstract-factory/MacFactory.java b/01-creational/abstract-factory/MacFactory.java new file mode 100644 index 0000000..0a027c1 --- /dev/null +++ b/01-creational/abstract-factory/MacFactory.java @@ -0,0 +1,6 @@ +package abstractfactory; + +public class MacFactory implements GUIFactory { + @Override public Button createButton() { return new MacButton(); } + @Override public Checkbox createCheckbox() { return new MacCheckbox(); } +} diff --git a/01-creational/abstract-factory/Main.java b/01-creational/abstract-factory/Main.java new file mode 100644 index 0000000..60981b9 --- /dev/null +++ b/01-creational/abstract-factory/Main.java @@ -0,0 +1,22 @@ +package abstractfactory; + +public class Main { + public static void main(String[] args) { + System.out.println("=== Abstract Factory Pattern Demo ===\n"); + + String os = System.getProperty("os.name", "Windows").toLowerCase(); + GUIFactory factory = os.contains("mac") ? new MacFactory() : new WindowsFactory(); + + System.out.println("Detected OS family: " + (os.contains("mac") ? "Mac" : "Windows")); + System.out.println(); + + Application app = new Application(factory); + app.render(); + app.simulateClick(); + + System.out.println("\n--- Forcing Mac UI ---"); + Application macApp = new Application(new MacFactory()); + macApp.render(); + macApp.simulateClick(); + } +} diff --git a/01-creational/abstract-factory/WindowsButton.java b/01-creational/abstract-factory/WindowsButton.java new file mode 100644 index 0000000..c93ad4b --- /dev/null +++ b/01-creational/abstract-factory/WindowsButton.java @@ -0,0 +1,6 @@ +package abstractfactory; + +public class WindowsButton implements Button { + @Override public void render() { System.out.println("[Windows] Rendering button with square corners"); } + @Override public void onClick() { System.out.println("[Windows] Button clicked - raised border effect"); } +} diff --git a/01-creational/abstract-factory/WindowsCheckbox.java b/01-creational/abstract-factory/WindowsCheckbox.java new file mode 100644 index 0000000..91fb697 --- /dev/null +++ b/01-creational/abstract-factory/WindowsCheckbox.java @@ -0,0 +1,5 @@ +package abstractfactory; + +public class WindowsCheckbox implements Checkbox { + @Override public void render() { System.out.println("[Windows] Rendering checkbox with square tick box"); } +} diff --git a/01-creational/abstract-factory/WindowsFactory.java b/01-creational/abstract-factory/WindowsFactory.java new file mode 100644 index 0000000..3f3c63b --- /dev/null +++ b/01-creational/abstract-factory/WindowsFactory.java @@ -0,0 +1,6 @@ +package abstractfactory; + +public class WindowsFactory implements GUIFactory { + @Override public Button createButton() { return new WindowsButton(); } + @Override public Checkbox createCheckbox() { return new WindowsCheckbox(); } +} diff --git a/01-creational/builder/Director.java b/01-creational/builder/Director.java new file mode 100644 index 0000000..642f7e4 --- /dev/null +++ b/01-creational/builder/Director.java @@ -0,0 +1,12 @@ +package builder; + +/** Director knows how to build common configurations */ +public class Director { + public House buildStarter(House.Builder builder) { + return builder.rooms(2).floors(1).garage(false).roofType("gabled").build(); + } + + public House buildLuxury(House.Builder builder) { + return builder.rooms(6).floors(3).garage(true).garden(true).pool(true).roofType("hip").build(); + } +} diff --git a/01-creational/builder/House.java b/01-creational/builder/House.java new file mode 100644 index 0000000..9d615b5 --- /dev/null +++ b/01-creational/builder/House.java @@ -0,0 +1,43 @@ +package builder; + +public class House { + private final int rooms; + private final int floors; + private final boolean hasGarage; + private final boolean hasGarden; + private final boolean hasPool; + private final String roofType; + + private House(Builder builder) { + this.rooms = builder.rooms; + this.floors = builder.floors; + this.hasGarage = builder.hasGarage; + this.hasGarden = builder.hasGarden; + this.hasPool = builder.hasPool; + this.roofType = builder.roofType; + } + + @Override + public String toString() { + return "House{rooms=" + rooms + ", floors=" + floors + + ", garage=" + hasGarage + ", garden=" + hasGarden + + ", pool=" + hasPool + ", roof='" + roofType + "'}"; + } + + public static class Builder { + private int rooms = 1; + private int floors = 1; + private boolean hasGarage = false; + private boolean hasGarden = false; + private boolean hasPool = false; + private String roofType = "flat"; + + public Builder rooms(int rooms) { this.rooms = rooms; return this; } + public Builder floors(int floors) { this.floors = floors; return this; } + public Builder garage(boolean v) { this.hasGarage = v; return this; } + public Builder garden(boolean v) { this.hasGarden = v; return this; } + public Builder pool(boolean v) { this.hasPool = v; return this; } + public Builder roofType(String roofType) { this.roofType = roofType; return this; } + public House build() { return new House(this); } + } +} diff --git a/01-creational/builder/Main.java b/01-creational/builder/Main.java new file mode 100644 index 0000000..02a641b --- /dev/null +++ b/01-creational/builder/Main.java @@ -0,0 +1,20 @@ +package builder; + +public class Main { + public static void main(String[] args) { + System.out.println("=== Builder Pattern Demo ===\n"); + + Director director = new Director(); + + House starter = director.buildStarter(new House.Builder()); + System.out.println("Starter home : " + starter); + + House luxury = director.buildLuxury(new House.Builder()); + System.out.println("Luxury home : " + luxury); + + // Client builds a custom house directly without the Director + House custom = new House.Builder() + .rooms(4).floors(2).garden(true).roofType("mansard").build(); + System.out.println("Custom home : " + custom); + } +} diff --git a/01-creational/factory-method/EmailNotification.java b/01-creational/factory-method/EmailNotification.java new file mode 100644 index 0000000..68bc54c --- /dev/null +++ b/01-creational/factory-method/EmailNotification.java @@ -0,0 +1,11 @@ +package factorymethod; + +public class EmailNotification implements Notification { + private final String email; + public EmailNotification(String email) { this.email = email; } + + @Override + public void send(String message) { + System.out.println("Email -> " + email + ": " + message); + } +} diff --git a/01-creational/factory-method/EmailService.java b/01-creational/factory-method/EmailService.java new file mode 100644 index 0000000..b193545 --- /dev/null +++ b/01-creational/factory-method/EmailService.java @@ -0,0 +1,11 @@ +package factorymethod; + +public class EmailService extends NotificationService { + private final String email; + public EmailService(String email) { this.email = email; } + + @Override + protected Notification createNotification() { + return new EmailNotification(email); + } +} diff --git a/01-creational/factory-method/Main.java b/01-creational/factory-method/Main.java new file mode 100644 index 0000000..11f9084 --- /dev/null +++ b/01-creational/factory-method/Main.java @@ -0,0 +1,17 @@ +package factorymethod; + +public class Main { + public static void main(String[] args) { + System.out.println("=== Factory Method Pattern Demo ===\n"); + + NotificationService[] services = { + new EmailService("alice@example.com"), + new SmsService("+1-555-0123"), + new PushService("device-token-abc123") + }; + + for (NotificationService service : services) { + service.notifyUser("Your order #1042 has been shipped!"); + } + } +} diff --git a/01-creational/factory-method/Notification.java b/01-creational/factory-method/Notification.java new file mode 100644 index 0000000..b09e01f --- /dev/null +++ b/01-creational/factory-method/Notification.java @@ -0,0 +1,5 @@ +package factorymethod; + +public interface Notification { + void send(String message); +} diff --git a/01-creational/factory-method/NotificationService.java b/01-creational/factory-method/NotificationService.java new file mode 100644 index 0000000..dc51828 --- /dev/null +++ b/01-creational/factory-method/NotificationService.java @@ -0,0 +1,11 @@ +package factorymethod; + +/** Creator - declares the factory method */ +public abstract class NotificationService { + protected abstract Notification createNotification(); + + public void notifyUser(String message) { + Notification n = createNotification(); + n.send(message); + } +} diff --git a/01-creational/factory-method/PushNotification.java b/01-creational/factory-method/PushNotification.java new file mode 100644 index 0000000..8b4c3b8 --- /dev/null +++ b/01-creational/factory-method/PushNotification.java @@ -0,0 +1,11 @@ +package factorymethod; + +public class PushNotification implements Notification { + private final String deviceToken; + public PushNotification(String deviceToken) { this.deviceToken = deviceToken; } + + @Override + public void send(String message) { + System.out.println("Push -> " + deviceToken + ": " + message); + } +} diff --git a/01-creational/factory-method/PushService.java b/01-creational/factory-method/PushService.java new file mode 100644 index 0000000..1809b9c --- /dev/null +++ b/01-creational/factory-method/PushService.java @@ -0,0 +1,11 @@ +package factorymethod; + +public class PushService extends NotificationService { + private final String token; + public PushService(String token) { this.token = token; } + + @Override + protected Notification createNotification() { + return new PushNotification(token); + } +} diff --git a/01-creational/factory-method/SmsNotification.java b/01-creational/factory-method/SmsNotification.java new file mode 100644 index 0000000..f5d1dd6 --- /dev/null +++ b/01-creational/factory-method/SmsNotification.java @@ -0,0 +1,11 @@ +package factorymethod; + +public class SmsNotification implements Notification { + private final String phone; + public SmsNotification(String phone) { this.phone = phone; } + + @Override + public void send(String message) { + System.out.println("SMS -> " + phone + ": " + message); + } +} diff --git a/01-creational/factory-method/SmsService.java b/01-creational/factory-method/SmsService.java new file mode 100644 index 0000000..aab7156 --- /dev/null +++ b/01-creational/factory-method/SmsService.java @@ -0,0 +1,11 @@ +package factorymethod; + +public class SmsService extends NotificationService { + private final String phone; + public SmsService(String phone) { this.phone = phone; } + + @Override + protected Notification createNotification() { + return new SmsNotification(phone); + } +} diff --git a/01-creational/prototype/Circle.java b/01-creational/prototype/Circle.java new file mode 100644 index 0000000..16d3c90 --- /dev/null +++ b/01-creational/prototype/Circle.java @@ -0,0 +1,24 @@ +package prototype; + +public class Circle extends Shape { + private int radius; + + public Circle(int radius, String color) { + this.radius = radius; + this.color = color; + } + + /** Copy constructor used by clone() */ + private Circle(Circle source) { + super(source); + this.radius = source.radius; + } + + @Override + public Circle clone() { return new Circle(this); } + + @Override + public String toString() { + return "Circle{color=" + color + ", radius=" + radius + ", pos=(" + x + "," + y + ")}"; + } +} diff --git a/01-creational/prototype/Main.java b/01-creational/prototype/Main.java new file mode 100644 index 0000000..8743e33 --- /dev/null +++ b/01-creational/prototype/Main.java @@ -0,0 +1,33 @@ +package prototype; + +import java.util.ArrayList; +import java.util.List; + +public class Main { + public static void main(String[] args) { + System.out.println("=== Prototype Pattern Demo ===\n"); + + List originals = new ArrayList<>(); + originals.add(new Circle(10, "red")); + originals.add(new Rectangle(20, 30, "blue")); + + // Clone each shape - no need to know the concrete type + List copies = new ArrayList<>(); + for (Shape shape : originals) { + copies.add(shape.clone()); + } + + // Mutate copies - originals are unaffected + copies.get(0).setColor("green"); + copies.get(0).move(5, 5); + copies.get(1).setColor("yellow"); + + System.out.println("--- Originals ---"); + originals.forEach(System.out::println); + + System.out.println("\n--- Clones (mutated) ---"); + copies.forEach(System.out::println); + + System.out.println("\nSame instance? " + (originals.get(0) == copies.get(0))); + } +} diff --git a/01-creational/prototype/Rectangle.java b/01-creational/prototype/Rectangle.java new file mode 100644 index 0000000..3951100 --- /dev/null +++ b/01-creational/prototype/Rectangle.java @@ -0,0 +1,26 @@ +package prototype; + +public class Rectangle extends Shape { + private int width; + private int height; + + public Rectangle(int width, int height, String color) { + this.width = width; + this.height = height; + this.color = color; + } + + private Rectangle(Rectangle source) { + super(source); + this.width = source.width; + this.height = source.height; + } + + @Override + public Rectangle clone() { return new Rectangle(this); } + + @Override + public String toString() { + return "Rectangle{color=" + color + ", size=" + width + "x" + height + ", pos=(" + x + "," + y + ")}"; + } +} diff --git a/01-creational/prototype/Shape.java b/01-creational/prototype/Shape.java new file mode 100644 index 0000000..0ee3b07 --- /dev/null +++ b/01-creational/prototype/Shape.java @@ -0,0 +1,22 @@ +package prototype; + +/** Prototype - every shape can clone itself */ +public abstract class Shape { + protected String color; + protected int x; + protected int y; + + protected Shape(Shape source) { + this.color = source.color; + this.x = source.x; + this.y = source.y; + } + + protected Shape() {} + + public abstract Shape clone(); + + public void setColor(String color) { this.color = color; } + public String getColor() { return color; } + public void move(int x, int y) { this.x = x; this.y = y; } +} diff --git a/01-creational/singleton/DatabaseConnection.java b/01-creational/singleton/DatabaseConnection.java new file mode 100644 index 0000000..5da70fc --- /dev/null +++ b/01-creational/singleton/DatabaseConnection.java @@ -0,0 +1,34 @@ +package singleton; + +/** + * Thread-safe Singleton using double-checked locking. + */ +public class DatabaseConnection { + private static volatile DatabaseConnection instance; + private final String url; + private int queryCount = 0; + + private DatabaseConnection() { + this.url = "jdbc:mysql://localhost:3306/myapp"; + System.out.println("Establishing connection to " + url); + } + + public static DatabaseConnection getInstance() { + if (instance == null) { + synchronized (DatabaseConnection.class) { + if (instance == null) { + instance = new DatabaseConnection(); + } + } + } + return instance; + } + + public String executeQuery(String sql) { + queryCount++; + return "Result #" + queryCount + " for: " + sql; + } + + public int getQueryCount() { return queryCount; } + public String getUrl() { return url; } +} diff --git a/01-creational/singleton/Main.java b/01-creational/singleton/Main.java new file mode 100644 index 0000000..a45d237 --- /dev/null +++ b/01-creational/singleton/Main.java @@ -0,0 +1,19 @@ +package singleton; + +public class Main { + public static void main(String[] args) { + System.out.println("=== Singleton Pattern Demo ===\n"); + + DatabaseConnection c1 = DatabaseConnection.getInstance(); + DatabaseConnection c2 = DatabaseConnection.getInstance(); + DatabaseConnection c3 = DatabaseConnection.getInstance(); + + System.out.println("\nAll three references same instance? " + (c1 == c2 && c2 == c3)); + + System.out.println(c1.executeQuery("SELECT * FROM users")); + System.out.println(c2.executeQuery("SELECT * FROM orders")); + System.out.println(c3.executeQuery("SELECT COUNT(*) FROM products")); + + System.out.println("\nTotal queries: " + c1.getQueryCount()); + } +} diff --git a/PUSH-TO-GITEA.bat b/PUSH-TO-GITEA.bat deleted file mode 100644 index 0dd548c..0000000 --- a/PUSH-TO-GITEA.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -powershell -ExecutionPolicy Bypass -NoExit -File "%~dp0push-to-gitea.ps1" diff --git a/README.md b/README.md index b587967..9c6eed8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # GoF Design Patterns in Java -Complete runnable Java 17 implementations of all 23 Gang of Four design patterns. Each pattern has a dedicated article at [ankurm.com](https://ankurm.com/gof-design-patterns-java/) with a UML diagram, step-by-step explanation, and console output. +Complete runnable Java 17 implementations of all 23 Gang of Four design patterns. +Each pattern has a dedicated article at [ankurm.com](https://ankurm.com/gof-design-patterns-java/) +with a UML diagram, step-by-step explanation, and console output. ## Structure @@ -41,27 +43,16 @@ design-patterns/ ## Run any pattern -```powershell -# Windows (PowerShell) -$JAVAC = 'C:\Program Files\Eclipse Adoptium\jdk-17.0.7.7-hotspot\bin\javac.exe' -$JAVA = 'C:\Program Files\Eclipse Adoptium\jdk-17.0.7.7-hotspot\bin\java.exe' - -& $JAVAC 03-behavioral/strategy/*.java -d out/strategy -& $JAVA -cp out/strategy strategy.Main -``` - ```bash -# Linux / macOS +# Linux / macOS / Git Bash (Windows) javac 03-behavioral/strategy/*.java -d out/strategy java -cp out/strategy strategy.Main ``` -## Run all behavioral patterns (Windows) - -Double-click `RUN-behavioral.bat` or run in PowerShell: - -```powershell -powershell -ExecutionPolicy Bypass -File run-behavioral.ps1 +```cmd +REM Windows Command Prompt +javac 03-behavioral\strategy\*.java -d out\strategy +java -cp out\strategy strategy.Main ``` ## Articles diff --git a/RUN-behavioral.bat b/RUN-behavioral.bat deleted file mode 100644 index 1493ba2..0000000 --- a/RUN-behavioral.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -powershell -ExecutionPolicy Bypass -NoExit -Command "& 'C:\Users\Ankur\Claude\Projects\@ankurm Blog\design-patterns\run-behavioral.ps1'" diff --git a/RUN.bat b/RUN.bat deleted file mode 100644 index aa75621..0000000 --- a/RUN.bat +++ /dev/null @@ -1,2 +0,0 @@ -@echo off -powershell -ExecutionPolicy Bypass -NoExit -Command "& 'C:\Users\Ankur\Claude\Projects\@ankurm Blog\design-patterns\run-structural.ps1'" diff --git a/compile-and-run-structural.bat b/compile-and-run-structural.bat deleted file mode 100644 index bea0a85..0000000 --- a/compile-and-run-structural.bat +++ /dev/null @@ -1,74 +0,0 @@ -@echo off -setlocal - -set BASE=%~dp0 -set OUT=%BASE%\out - -echo ============================================================ -echo Compiling and running structural design pattern examples -echo ============================================================ - -:: Create output dir -if not exist "%OUT%" mkdir "%OUT%" - -:: --- Adapter --- -echo. -echo [1/7] ADAPTER -javac -d "%OUT%\adapter" -sourcepath "%BASE%\02-structural\adapter" "%BASE%\02-structural\adapter\*.java" 2>&1 -if errorlevel 1 (echo COMPILE ERROR - Adapter) else ( - java -cp "%OUT%\adapter" adapter.Main -) - -:: --- Bridge --- -echo. -echo [2/7] BRIDGE -javac -d "%OUT%\bridge" -sourcepath "%BASE%\02-structural\bridge" "%BASE%\02-structural\bridge\*.java" 2>&1 -if errorlevel 1 (echo COMPILE ERROR - Bridge) else ( - java -cp "%OUT%\bridge" bridge.Main -) - -:: --- Composite --- -echo. -echo [3/7] COMPOSITE -javac -d "%OUT%\composite" -sourcepath "%BASE%\02-structural\composite" "%BASE%\02-structural\composite\*.java" 2>&1 -if errorlevel 1 (echo COMPILE ERROR - Composite) else ( - java -cp "%OUT%\composite" composite.Main -) - -:: --- Decorator --- -echo. -echo [4/7] DECORATOR -javac -d "%OUT%\decorator" -sourcepath "%BASE%\02-structural\decorator" "%BASE%\02-structural\decorator\*.java" 2>&1 -if errorlevel 1 (echo COMPILE ERROR - Decorator) else ( - java -cp "%OUT%\decorator" decorator.Main -) - -:: --- Facade --- -echo. -echo [5/7] FACADE -javac -d "%OUT%\facade" -sourcepath "%BASE%\02-structural\facade" "%BASE%\02-structural\facade\*.java" 2>&1 -if errorlevel 1 (echo COMPILE ERROR - Facade) else ( - java -cp "%OUT%\facade" facade.Main -) - -:: --- Flyweight --- -echo. -echo [6/7] FLYWEIGHT -javac -d "%OUT%\flyweight" -sourcepath "%BASE%\02-structural\flyweight" "%BASE%\02-structural\flyweight\*.java" 2>&1 -if errorlevel 1 (echo COMPILE ERROR - Flyweight) else ( - java -cp "%OUT%\flyweight" flyweight.Main -) - -:: --- Proxy --- -echo. -echo [7/7] PROXY -javac -d "%OUT%\proxy" -sourcepath "%BASE%\02-structural\proxy" "%BASE%\02-structural\proxy\*.java" 2>&1 -if errorlevel 1 (echo COMPILE ERROR - Proxy) else ( - java -cp "%OUT%\proxy" proxy.Main -) - -echo. -echo ============================================================ -echo All structural patterns compiled and executed -echo ============================================================ -pause diff --git a/push-to-gitea.ps1 b/push-to-gitea.ps1 deleted file mode 100644 index 27d4301..0000000 --- a/push-to-gitea.ps1 +++ /dev/null @@ -1,50 +0,0 @@ -$REMOTE = "https://ankurm.com/git.app/asmhatre/design-patterns.git" -$BRANCH = "main" - -Set-Location $PSScriptRoot - -# Always run git init - it is safe and idempotent on an existing repo -git init - -# Configure remote -$existing = git remote get-url origin 2>$null -if ($LASTEXITCODE -ne 0) { - git remote add origin $REMOTE - Write-Host "Added remote." -ForegroundColor Green -} elseif ($existing.Trim() -ne $REMOTE) { - git remote set-url origin $REMOTE - Write-Host "Updated remote." -ForegroundColor Yellow -} else { - Write-Host "Remote OK: $REMOTE" -ForegroundColor Cyan -} - -# Create .gitignore if missing -if (-not (Test-Path ".gitignore")) { - Set-Content ".gitignore" "out/`n*.class`nscreenshots/*.png`n*.b64.txt" - Write-Host "Created .gitignore" -ForegroundColor Green -} - -# Stage and commit -git add -A -$status = git status --short - -if (-not $status) { - Write-Host "Nothing to commit - repo is up to date." -ForegroundColor Cyan - exit 0 -} - -Write-Host "`nFiles to commit:" -ForegroundColor Yellow -Write-Host $status - -$timestamp = Get-Date -Format "yyyy-MM-dd" -git commit -m "Add all 23 GoF design pattern implementations ($timestamp)" - -Write-Host "`nPushing to $REMOTE ..." -ForegroundColor Yellow -git push -u origin $BRANCH - -if ($LASTEXITCODE -eq 0) { - Write-Host "`nDone! Code live at $REMOTE" -ForegroundColor Green -} else { - Write-Host "`nPush failed. Try manually: git push -u origin main" -ForegroundColor Red - Write-Host "If prompted, enter your Gitea username and password." -ForegroundColor Yellow -} diff --git a/run-all.bat b/run-all.bat deleted file mode 100644 index 7d12222..0000000 --- a/run-all.bat +++ /dev/null @@ -1,80 +0,0 @@ -@echo off -setlocal EnableDelayedExpansion - -set BASE=%~dp0 -set JAVAC="C:\Program Files\Eclipse Adoptium\jdk-17.0.7.7-hotspot\bin\javac.exe" -set JAVA="C:\Program Files\Eclipse Adoptium\jdk-17.0.7.7-hotspot\bin\java.exe" -set LOG=%BASE%output.log - -echo Design Patterns - Compile and Run > "%LOG%" -echo Java: 17.0.7 (Eclipse Temurin) >> "%LOG%" -echo ================================ >> "%LOG%" - -:: Create output dirs -for %%P in (adapter bridge composite decorator facade flyweight proxy) do ( - if not exist "%BASE%out\%%P" mkdir "%BASE%out\%%P" -) - -:: Function-like subroutine to compile a package -:: Usage: CALL :compile_pkg - -:: --- ADAPTER --- -echo. >> "%LOG%" -echo === ADAPTER === >> "%LOG%" -set FILES= -for %%f in ("%BASE%02-structural\adapter\*.java") do set FILES=!FILES! "%%f" -%JAVAC% -d "%BASE%out\adapter" !FILES! >> "%LOG%" 2>&1 -if not errorlevel 1 (%JAVA% -cp "%BASE%out\adapter" adapter.Main >> "%LOG%" 2>&1) - -:: --- BRIDGE --- -echo. >> "%LOG%" -echo === BRIDGE === >> "%LOG%" -set FILES= -for %%f in ("%BASE%02-structural\bridge\*.java") do set FILES=!FILES! "%%f" -%JAVAC% -d "%BASE%out\bridge" !FILES! >> "%LOG%" 2>&1 -if not errorlevel 1 (%JAVA% -cp "%BASE%out\bridge" bridge.Main >> "%LOG%" 2>&1) - -:: --- COMPOSITE --- -echo. >> "%LOG%" -echo === COMPOSITE === >> "%LOG%" -set FILES= -for %%f in ("%BASE%02-structural\composite\*.java") do set FILES=!FILES! "%%f" -%JAVAC% -d "%BASE%out\composite" !FILES! >> "%LOG%" 2>&1 -if not errorlevel 1 (%JAVA% -cp "%BASE%out\composite" composite.Main >> "%LOG%" 2>&1) - -:: --- DECORATOR --- -echo. >> "%LOG%" -echo === DECORATOR === >> "%LOG%" -set FILES= -for %%f in ("%BASE%02-structural\decorator\*.java") do set FILES=!FILES! "%%f" -%JAVAC% -d "%BASE%out\decorator" !FILES! >> "%LOG%" 2>&1 -if not errorlevel 1 (%JAVA% -cp "%BASE%out\decorator" decorator.Main >> "%LOG%" 2>&1) - -:: --- FACADE --- -echo. >> "%LOG%" -echo === FACADE === >> "%LOG%" -set FILES= -for %%f in ("%BASE%02-structural\facade\*.java") do set FILES=!FILES! "%%f" -%JAVAC% -d "%BASE%out\facade" !FILES! >> "%LOG%" 2>&1 -if not errorlevel 1 (%JAVA% -cp "%BASE%out\facade" facade.Main >> "%LOG%" 2>&1) - -:: --- FLYWEIGHT --- -echo. >> "%LOG%" -echo === FLYWEIGHT === >> "%LOG%" -set FILES= -for %%f in ("%BASE%02-structural\flyweight\*.java") do set FILES=!FILES! "%%f" -%JAVAC% -d "%BASE%out\flyweight" !FILES! >> "%LOG%" 2>&1 -if not errorlevel 1 (%JAVA% -cp "%BASE%out\flyweight" flyweight.Main >> "%LOG%" 2>&1) - -:: --- PROXY --- -echo. >> "%LOG%" -echo === PROXY === >> "%LOG%" -set FILES= -for %%f in ("%BASE%02-structural\proxy\*.java") do set FILES=!FILES! "%%f" -%JAVAC% -d "%BASE%out\proxy" !FILES! >> "%LOG%" 2>&1 -if not errorlevel 1 (%JAVA% -cp "%BASE%out\proxy" proxy.Main >> "%LOG%" 2>&1) - -echo. >> "%LOG%" -echo [DONE] >> "%LOG%" - -notepad "%LOG%" diff --git a/run-behavioral.ps1 b/run-behavioral.ps1 deleted file mode 100644 index fa6cecb..0000000 --- a/run-behavioral.ps1 +++ /dev/null @@ -1,62 +0,0 @@ -$JAVAC = 'C:\Program Files\Eclipse Adoptium\jdk-17.0.7.7-hotspot\bin\javac.exe' -$JAVA = 'C:\Program Files\Eclipse Adoptium\jdk-17.0.7.7-hotspot\bin\java.exe' -$BASE = 'C:\Users\Ankur\Claude\Projects\@ankurm Blog\design-patterns' -$OUTDIR = "$BASE\screenshots" - -New-Item -Force -ItemType Directory $OUTDIR | Out-Null - -$patterns = @( - @{dir="chain-of-responsibility"; pkg="chain"; main="chain.Main"}, - @{dir="command"; pkg="command"; main="command.Main"}, - @{dir="iterator"; pkg="iterator"; main="iterator.Main"}, - @{dir="mediator"; pkg="mediator"; main="mediator.Main"}, - @{dir="memento"; pkg="memento"; main="memento.Main"}, - @{dir="observer"; pkg="observer"; main="observer.Main"}, - @{dir="state"; pkg="state"; main="state.Main"}, - @{dir="strategy"; pkg="strategy"; main="strategy.Main"}, - @{dir="template-method"; pkg="template"; main="template.Main"}, - @{dir="visitor"; pkg="visitor"; main="visitor.Main"} -) - -$allOk = $true - -foreach ($p in $patterns) { - $label = $p.dir.ToUpper() - Write-Host "`n=== $label ===" -ForegroundColor Cyan - - $srcDir = "$BASE\03-behavioral\$($p.dir)" - $outDir = "$BASE\out\$($p.pkg)" - New-Item -Force -ItemType Directory $outDir | Out-Null - - $files = @(Get-ChildItem "$srcDir\*.java" | Select-Object -ExpandProperty FullName) - - if ($files.Count -eq 0) { - Write-Host "[SKIP] No .java files in $srcDir" -ForegroundColor Yellow - continue - } - - $compileOut = & $JAVAC -d $outDir @files 2>&1 - if ($LASTEXITCODE -ne 0) { - Write-Host "[FAIL] $label compile error:" -ForegroundColor Red - $compileOut | ForEach-Object { Write-Host " $_" -ForegroundColor Red } - $allOk = $false - continue - } - - Write-Host "[OK] Compiled $($p.dir)" -ForegroundColor Green - - $logFile = "$OUTDIR\$($p.pkg)-output.txt" - $runOut = & $JAVA -cp $outDir $($p.main) 2>&1 - $runOut | Out-File -FilePath $logFile -Encoding utf8 - $runOut | ForEach-Object { Write-Host $_ } - Write-Host "[SAVED] $logFile" -ForegroundColor DarkGray -} - -Write-Host "`n============================================" -ForegroundColor Yellow -if ($allOk) { - Write-Host "All 10 behavioral patterns compiled and ran OK" -ForegroundColor Green -} else { - Write-Host "Some patterns had errors - check output above" -ForegroundColor Red -} -Write-Host "Output files: $OUTDIR" -ForegroundColor Yellow -Read-Host "`nPress Enter to close" diff --git a/run-structural.ps1 b/run-structural.ps1 deleted file mode 100644 index ea7e662..0000000 --- a/run-structural.ps1 +++ /dev/null @@ -1,61 +0,0 @@ -$JAVAC = 'C:\Program Files\Eclipse Adoptium\jdk-17.0.7.7-hotspot\bin\javac.exe' -$JAVA = 'C:\Program Files\Eclipse Adoptium\jdk-17.0.7.7-hotspot\bin\java.exe' -$BASE = 'C:\Users\Ankur\Claude\Projects\@ankurm Blog\design-patterns' -$OUTDIR = "$BASE\screenshots" - -New-Item -Force -ItemType Directory $OUTDIR | Out-Null - -$patterns = @( - @{dir="adapter"; main="adapter.Main"}, - @{dir="bridge"; main="bridge.Main"}, - @{dir="composite"; main="composite.Main"}, - @{dir="decorator"; main="decorator.Main"}, - @{dir="facade"; main="facade.Main"}, - @{dir="flyweight"; main="flyweight.Main"}, - @{dir="proxy"; main="proxy.Main"} -) - -$allOk = $true - -foreach ($p in $patterns) { - $label = $p.dir.ToUpper() - Write-Host "`n=== $label ===" -ForegroundColor Cyan - - $srcDir = "$BASE\02-structural\$($p.dir)" - $outDir = "$BASE\out\$($p.dir)" - New-Item -Force -ItemType Directory $outDir | Out-Null - - $files = @(Get-ChildItem "$srcDir\*.java" | Select-Object -ExpandProperty FullName) - - if ($files.Count -eq 0) { - Write-Host "[SKIP] No .java files in $srcDir" -ForegroundColor Yellow - continue - } - - # Compile - $compileOut = & $JAVAC -d $outDir @files 2>&1 - if ($LASTEXITCODE -ne 0) { - Write-Host "[FAIL] $label compile error:" -ForegroundColor Red - $compileOut | ForEach-Object { Write-Host " $_" -ForegroundColor Red } - $allOk = $false - continue - } - - Write-Host "[OK] Compiled $($p.dir)" -ForegroundColor Green - - # Run and save to per-pattern file - $logFile = "$OUTDIR\$($p.dir)-output.txt" - $runOut = & $JAVA -cp $outDir $($p.main) 2>&1 - $runOut | Out-File -FilePath $logFile -Encoding utf8 - $runOut | ForEach-Object { Write-Host $_ } - Write-Host "[SAVED] $logFile" -ForegroundColor DarkGray -} - -Write-Host "`n============================================" -ForegroundColor Yellow -if ($allOk) { - Write-Host "All 7 structural patterns compiled and ran OK" -ForegroundColor Green -} else { - Write-Host "Some patterns had errors - check output above" -ForegroundColor Red -} -Write-Host "Output files: $OUTDIR" -ForegroundColor Yellow -Read-Host "`nPress Enter to close"