Add creational patterns, Interpreter; remove scripts; update README

This commit is contained in:
2026-06-13 16:22:13 +00:00
parent a5beb61425
commit 2f684bf3d7
38 changed files with 435 additions and 350 deletions

View File

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

View File

@@ -0,0 +1,6 @@
package abstractfactory;
public interface Button {
void render();
void onClick();
}

View File

@@ -0,0 +1,5 @@
package abstractfactory;
public interface Checkbox {
void render();
}

View File

@@ -0,0 +1,7 @@
package abstractfactory;
/** Abstract Factory - creates families of related UI components */
public interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}

View File

@@ -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"); }
}

View File

@@ -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"); }
}

View File

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

View File

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

View File

@@ -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"); }
}

View File

@@ -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"); }
}

View File

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

View File

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

View File

@@ -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); }
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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!");
}
}
}

View File

@@ -0,0 +1,5 @@
package factorymethod;
public interface Notification {
void send(String message);
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

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

View File

@@ -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<Shape> 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<Shape> 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)));
}
}

View File

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

View File

@@ -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; }
}

View File

@@ -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; }
}

View File

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

View File

@@ -1,2 +0,0 @@
@echo off
powershell -ExecutionPolicy Bypass -NoExit -File "%~dp0push-to-gitea.ps1"

View File

@@ -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

View File

@@ -1,2 +0,0 @@
@echo off
powershell -ExecutionPolicy Bypass -NoExit -Command "& 'C:\Users\Ankur\Claude\Projects\@ankurm Blog\design-patterns\run-behavioral.ps1'"

View File

@@ -1,2 +0,0 @@
@echo off
powershell -ExecutionPolicy Bypass -NoExit -Command "& 'C:\Users\Ankur\Claude\Projects\@ankurm Blog\design-patterns\run-structural.ps1'"

View File

@@ -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

View File

@@ -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
}

View File

@@ -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 <package> <relative_src_dir>
:: --- 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%"

View File

@@ -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"

View File

@@ -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"