private logs: string[] = [];
private constructor() {
// Private constructor
}
static getInstance(): Logger {
if (!Logger.instance) {
Logger.instance = new Logger();
}
return Logger.instance;
}
log(message: string): void {
const timestamp = new Date().toISOString();
this.logs.push([${timestamp}] ${message});
console.log([${timestamp}] ${message});
}
getLogs(): string[] {
return [...this.logs];
}```
}
// Usage
const logger1 = Logger.getInstance();
const logger2 = Logger.getInstance();
logger1.log("Application started");
console.log(logger1 === logger2); // true - same instance
### Python Implementation
```python
class ConfigManager:
```python
"""Thread-safe singleton with __new__."""
_instance = None
_lock = threading.Lock()
def __new__(cls):
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self):
if self._initialized:
return
self.config = self._load_config()
self._initialized = True
def _load_config(self):
return {"api_url": "https://api.contoso.com", "timeout": 30}
def get(self, key):
return self.config.get(key)
Usage
config1 = ConfigManager()
config2 = ConfigManager()
print(config1 is config2) # True
**Modern alternative - Dependency Injection:**
```typescript
// Instead of Singleton, use DI container
interface ILogger {
```text
log(message: string): void;```
}
class ConsoleLogger implements ILogger {
```javascript
log(message: string): void {
console.log(message);
}```
}
// Register in DI container
container.register<ILogger>("ILogger", ConsoleLogger, { lifecycle: "singleton" });
// Inject dependency
class UserService {
```text
constructor(private logger: ILogger) {}
createUser(name: string): void {
this.logger.log(`Creating user: ${name}`);
}```
}
Factory Pattern
Purpose

Create objects without specifying exact class, delegating instantiation to subclasses.
Simple Factory (C#)
// Product interface
public interface INotification
{
```text
void Send(string message);```
}
// Concrete products
public class EmailNotification : INotification
{
```text
public void Send(string message)
{
Console.WriteLine($"Email: {message}");
}```
}
public class SMSNotification : INotification
{
```text
public void Send(string message)
{
Console.WriteLine($"SMS: {message}");
}```
}
public class PushNotification : INotification
{
```text
public void Send(string message)
{
Console.WriteLine($"Push: {message}");
}```
}
// Factory
public class NotificationFactory
{
```javascript
public static INotification Create(string type)
{
return type.ToLower() switch
{
"email" => new EmailNotification(),
"sms" => new SMSNotification(),
"push" => new PushNotification(),
_ => throw new ArgumentException($"Unknown type: {type}")
};
}```
}
// Usage
var notification = NotificationFactory.Create("email");
notification.Send("Hello, World!");
Factory Method (TypeScript)
// Product interface
interface IDocument {
```text
open(): void;
save(): void;```
}
// Concrete products
class PDFDocument implements IDocument {
```javascript
open(): void {
console.log("Opening PDF document");
}
save(): void {
console.log("Saving PDF document");
}```
}
class WordDocument implements IDocument {
```javascript
open(): void {
console.log("Opening Word document");
}
save(): void {
console.log("Saving Word document");
}```
}
// Creator abstract class
abstract class DocumentCreator {
```javascript
abstract createDocument(): IDocument;
openDocument(): void {
const doc = this.createDocument();
doc.open();
}```
}
// Concrete creators
class PDFCreator extends DocumentCreator {
```text
createDocument(): IDocument {
return new PDFDocument();
}```
}
class WordCreator extends DocumentCreator {
```text
createDocument(): IDocument {
return new WordDocument();
}```
}
// Usage
const pdfCreator = new PDFCreator();
pdfCreator.openDocument(); // Opens PDF
const wordCreator = new WordCreator();
wordCreator.openDocument(); // Opens Word
Abstract Factory (Python)
from abc import ABC, abstractmethod
## Abstract products
class Button(ABC):
```python
@abstractmethod
def render(self): pass
class Checkbox(ABC):
@abstractmethod
def render(self): pass

Concrete products - Windows
class WindowsButton(Button):
def render(self):
return "Rendering Windows button"
class WindowsCheckbox(Checkbox):
def render(self):
return "Rendering Windows checkbox"

Concrete products - macOS
class MacButton(Button):
def render(self):
return "Rendering Mac button"
class MacCheckbox(Checkbox):
def render(self):
return "Rendering Mac checkbox"

Abstract factory
Figure: Configuration and management dashboard with status overview.
class GUIFactory(ABC):
@abstractmethod
def create_button(self) -> Button: pass

@abstractmethod
def create_checkbox(self) -> Checkbox: pass
Concrete factories
Figure: Configuration and management dashboard with status overview.
class WindowsFactory(GUIFactory):
def create_button(self) -> Button:
return WindowsButton()

def create_checkbox(self) -> Checkbox:
return WindowsCheckbox()
class MacFactory(GUIFactory):
def create_button(self) -> Button:
return MacButton()
def create_checkbox(self) -> Checkbox:
return MacCheckbox()
Usage
def create_ui(factory: GUIFactory):
button = factory.create_button()
checkbox = factory.create_checkbox()
print(button.render())
print(checkbox.render())
import platform
factory = WindowsFactory() if platform.system() == "Windows" else MacFactory()
create_ui(factory)



## Observer Pattern
### Purpose

Define one-to-many dependency where state changes notify all dependents automatically.
### C# with Events
```csharp
// Subject
public class StockMarket
{
```javascript
public event EventHandler<StockPriceChangedEventArgs> PriceChanged;
private decimal _price;
public decimal Price
{
get => _price;
set
{
if (_price != value)
{
var oldPrice = _price;
_price = value;
OnPriceChanged(new StockPriceChangedEventArgs(oldPrice, value));
}
}
}
protected virtual void OnPriceChanged(StockPriceChangedEventArgs e)
{
PriceChanged?.Invoke(this, e);
}```
}
public class StockPriceChangedEventArgs : EventArgs
{
```text
public decimal OldPrice { get; }
public decimal NewPrice { get; }
public StockPriceChangedEventArgs(decimal oldPrice, decimal newPrice)
{
OldPrice = oldPrice;
NewPrice = newPrice;
}```
}
// Observers
public class StockDisplay
{
```python
public void Subscribe(StockMarket market)
{
market.PriceChanged += OnPriceChanged;
}
private void OnPriceChanged(object sender, StockPriceChangedEventArgs e)
{
Console.WriteLine($"Display: Price changed from {e.OldPrice} to {e.NewPrice}");
}```
}
public class StockAlert
{
```text
private decimal _threshold;
public StockAlert(decimal threshold)
{
_threshold = threshold;
}
public void Subscribe(StockMarket market)
{
market.PriceChanged += OnPriceChanged;
}
private void OnPriceChanged(object sender, StockPriceChangedEventArgs e)
{
if (e.NewPrice > _threshold)
{
Console.WriteLine($"ALERT: Price exceeded {_threshold}!");
}
}```
}
// Usage
var market = new StockMarket { Price = 100 };
var display = new StockDisplay();
var alert = new StockAlert(150);
display.Subscribe(market);
alert.Subscribe(market);
market.Price = 120; // Triggers display
market.Price = 160; // Triggers both display and alert
TypeScript with RxJS
import { Subject } from 'rxjs';
import { filter, map } from 'rxjs/operators';
interface User {
```yaml
id: number;
name: string;
status: 'online' | 'offline';```
}
class UserService {
```text
private userStatusSubject = new Subject<User>();
userStatus$ = this.userStatusSubject.asObservable();
updateUserStatus(user: User): void {
this.userStatusSubject.next(user);
}```
}
// Observers
class NotificationService {
```javascript
constructor(private userService: UserService) {
this.userService.userStatus$
.pipe(filter(user => user.status === 'online'))
.subscribe(user => {
console.log(`Notification: ${user.name} is now online`);
});
}```
}
class ActivityLogger {
```javascript
constructor(private userService: UserService) {
this.userService.userStatus$.subscribe(user => {
console.log(`Log: User ${user.id} status: ${user.status}`);
});
}```
}
// Usage
const userService = new UserService();
const notifications = new NotificationService(userService);
const logger = new ActivityLogger(userService);
userService.updateUserStatus({ id: 1, name: 'Alice', status: 'online' });
// Output:
// Log: User 1 status: online
// Notification: Alice is now online
Python with Custom Observer
from abc import ABC, abstractmethod
from typing import List
## Observer interface
class Observer(ABC):
```python
@abstractmethod
def update(self, subject: 'Subject') -> None:
pass

Subject
Figure: Configuration and management dashboard with status overview.
class Subject:
def __init__(self):
self._observers: List[Observer] = []
self._state = None

def attach(self, observer: Observer) -> None:
self._observers.append(observer)
def detach(self, observer: Observer) -> None:
self._observers.remove(observer)
def notify(self) -> None:
for observer in self._observers:
observer.update(self)
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
self.notify()
Concrete observers
Figure: Configuration and management dashboard with status overview.
class EmailNotifier(Observer):
def update(self, subject: Subject) -> None:
print(f"Email: State changed to {subject.state}")
class SMSNotifier(Observer):
def update(self, subject: Subject) -> None:
if subject.state == "critical":
print(f"SMS Alert: Critical state!")
class Logger(Observer):
def update(self, subject: Subject) -> None:

print(f"Log: State = {subject.state}")
Usage
Figure: Configuration and management dashboard with status overview.
subject = Subject()
email = EmailNotifier()
sms = SMSNotifier()
logger = Logger()
subject.attach(email)
subject.attach(sms)
subject.attach(logger)
subject.state = "normal" # All observers notified
subject.state = "critical" # SMS sends alert
## Strategy Pattern
### Purpose

Define family of algorithms, encapsulate each, make them interchangeable.
### C# Implementation
```csharp
// Strategy interface
public interface IPaymentStrategy
{
```text
void Pay(decimal amount);```
}
// Concrete strategies
public class CreditCardPayment : IPaymentStrategy
{
```sql
private string _cardNumber;
public CreditCardPayment(string cardNumber)
{
_cardNumber = cardNumber;
}
public void Pay(decimal amount)
{
Console.WriteLine($"Paid ${amount} with credit card {_cardNumber}");
}```
}
public class PayPalPayment : IPaymentStrategy
{
```text
private string _email;
public PayPalPayment(string email)
{
_email = email;
}
public void Pay(decimal amount)
{
Console.WriteLine($"Paid ${amount} via PayPal to {_email}");
}```
}
public class BitcoinPayment : IPaymentStrategy
{
```text
private string _walletAddress;
public BitcoinPayment(string walletAddress)
{
_walletAddress = walletAddress;
}
public void Pay(decimal amount)
{
Console.WriteLine($"Paid ${amount} in Bitcoin to {_walletAddress}");
}```
}
// Context
public class ShoppingCart
{
```text
private IPaymentStrategy _paymentStrategy;
public void SetPaymentStrategy(IPaymentStrategy strategy)
{
_paymentStrategy = strategy;
}
public void Checkout(decimal amount)
{
_paymentStrategy.Pay(amount);
}```
}
// Usage
var cart = new ShoppingCart();
cart.SetPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456"));
cart.Checkout(99.99m);
cart.SetPaymentStrategy(new PayPalPayment("user@contoso.com"));
cart.Checkout(49.99m);
TypeScript with Functional Approach
// Strategy as function type
type CompressionStrategy = (data: string) => string;
// Concrete strategies as functions
const zipCompression: CompressionStrategy = (data) => {
```text
return `ZIP compressed: ${data}`;```
};
const gzipCompression: CompressionStrategy = (data) => {
```text
return `GZIP compressed: ${data}`;```
};
const lzmaCompression: CompressionStrategy = (data) => {
```text
return `LZMA compressed: ${data}`;```
};
// Context
class FileCompressor {
```text
private strategy: CompressionStrategy;
constructor(strategy: CompressionStrategy) {
this.strategy = strategy;
}
setStrategy(strategy: CompressionStrategy): void {
this.strategy = strategy;
}
compress(data: string): string {
return this.strategy(data);
}```
}
// Usage
const compressor = new FileCompressor(zipCompression);
console.log(compressor.compress("data")); // ZIP compressed: data
compressor.setStrategy(gzipCompression);
console.log(compressor.compress("data")); // GZIP compressed: data
Python with Duck Typing
## Strategy classes (no interface needed in Python)
class QuickSort:
```python
def sort(self, data: list) -> list:
if len(data) <= 1:
return data
pivot = data[len(data) // 2]
left = [x for x in data if x < pivot]
middle = [x for x in data if x == pivot]
right = [x for x in data if x > pivot]
return self.sort(left) + middle + self.sort(right)
class BubbleSort:
def sort(self, data: list) -> list:

arr = data.copy()
n = len(arr)
for i in range(n):
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
class MergeSort:
def sort(self, data: list) -> list:
if len(data) <= 1:
return data
mid = len(data) // 2
left = self.sort(data[:mid])
right = self.sort(data[mid:])
return self._merge(left, right)
def _merge(self, left: list, right: list) -> list:
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:])
result.extend(right[j:])
return result
Context
Figure: Configuration and management dashboard with status overview.
class Sorter:
def __init__(self, strategy):
self._strategy = strategy

def set_strategy(self, strategy):
self._strategy = strategy
def sort(self, data: list) -> list:
return self._strategy.sort(data)
Usage
Figure: Configuration and management dashboard with status overview.
data = [64, 34, 25, 12, 22, 11, 90]
sorter = Sorter(QuickSort())
print(sorter.sort(data)) # Quick sorted
sorter.set_strategy(BubbleSort())
print(sorter.sort(data)) # Bubble sorted
## Best Practices
1. **Singleton**: Use dependency injection instead when possible
2. **Factory**: Prefer factory methods for simple cases, abstract factory for families
3. **Observer**: Clean up subscriptions to prevent memory leaks
4. **Strategy**: Use functional approach in languages supporting first-class functions

## Architecture Decision and Tradeoffs
When designing software development solutions with Programming Languages, consider these key architectural trade-offs:
| Approach | Best For | Tradeoff |
|----------|----------|----------|
| Managed / platform service | Rapid delivery, reduced ops burden | Less customisation, potential vendor lock-in |
| Custom / self-hosted | Full control, advanced tuning | Higher operational overhead and cost |
> **Recommendation:** Start with the managed approach for most workloads and move to custom only when specific requirements demand it.
## Validation and Versioning
- Last validated: April 2026
- Validate examples against your tenant, region, and SKU constraints before production rollout.
- Keep module, CLI, and SDK versions pinned in automation pipelines and review quarterly.
## Security and Governance Considerations
- Apply least-privilege access using RBAC roles and just-in-time elevation for admin tasks.
- Store secrets in managed secret stores and avoid embedding credentials in scripts or source files.
- Enable audit logging, data protection policies, and periodic access reviews for regulated workloads.
## Cost and Performance Notes
- Define budgets and alerts, then monitor usage and cost trends continuously after go-live.
- Baseline performance with synthetic and real-user checks before and after major changes.
- Scale resources with measured thresholds and revisit sizing after usage pattern changes.
## Official Microsoft References
- https://learn.microsoft.com/
- https://learn.microsoft.com/azure/
- https://learn.microsoft.com/power-platform/
- https://learn.microsoft.com/microsoft-365/
## Public Examples from Official Sources
- These examples are sourced from official public Microsoft documentation and sample repositories.
- Documentation examples: https://learn.microsoft.com/training/
- Sample repositories: https://github.com/microsoft
- Prefer adapting these examples to your tenant, subscriptions, and governance requirements before production use.
## Key Takeaways
- Singleton ensures single instance but hinders testability (prefer DI)
- Factory pattern abstracts object creation, improving flexibility
- Observer enables loose coupling between subject and observers
- Strategy allows runtime algorithm selection without conditional logic
- Design patterns solve recurring problems but shouldn't be overused

## Next Steps
- Learn **Decorator pattern** for adding behavior dynamically
- Explore **Command pattern** for undo/redo functionality
- Study **Repository pattern** for data access abstraction
- Master **CQRS pattern** for separating read/write operations
## Additional Resources
- [Design Patterns: Elements of Reusable Object-Oriented Software](https://en.wikipedia.org/wiki/Design_Patterns)
- [Refactoring Guru](https://refactoring.guru/design-patterns)
- [Source Making](https://sourcemaking.com/design_patterns)
---
*Patterns are solutions, not rules.*