Skip to content

Repository files navigation

DesignAlgorithmsKit

TestscodecovDocumentation

A Swift package providing common design patterns and algorithms with protocols and base types for extensibility.

Overview

DesignAlgorithmsKit provides implementations of:

  • Design Patterns: Classic patterns (Gang of Four) and modern patterns commonly used in Swift development
  • Algorithms: Common algorithms and data structures (Merkle Tree, hashing, etc.)

All patterns and algorithms follow consistent implementation guidelines for maintainability, testability, and extensibility.

Features

Creational Patterns

  • Singleton Pattern - Thread-safe singleton implementations
  • Factory Pattern - Object creation without specifying concrete classes
  • Builder Pattern - Step-by-step object construction with fluent API
  • Prototype Pattern - Object cloning and copying
  • Dependency Injection - Protocol-based dependency injection

Structural Patterns

  • Adapter Pattern - Adapting interfaces to client expectations
  • Facade Pattern - Simplified interface to complex subsystems
  • Decorator Pattern - Adding behavior to objects dynamically
  • Composite Pattern - Composing objects into tree structures
  • Proxy Pattern - Controlling access to objects

Behavioral Patterns

  • Strategy Pattern - Interchangeable algorithms
  • Observer Pattern - Event notification and subscription
  • Queue Processing Pattern - Concurrent queue management with status tracking, progress monitoring, and retry support
  • Merging/Upsert Pattern - Configurable merge strategies for conflict resolution
  • Command Pattern - Encapsulating requests as objects
  • State Pattern - Object behavior based on state
  • Template Method Pattern - Defining algorithm skeleton
  • Chain of Responsibility - Passing requests along a chain
  • Job Manager Pattern - Orchestration of asynchronous tasks with status tracking
  • Pipeline Pattern - Type-erased async processing pipeline
  • Iterator Pattern - Traversing collections

Modern Patterns

  • Registry Pattern - Centralized type registration and discovery
  • Provider Pattern - Chain of responsibility for extensible behavior
  • Repository Pattern - Data access abstraction

Algorithms & Data Structures

  • Merkle Tree - Hash tree for efficient data verification
  • Bloom Filter - Probabilistic data structure for membership testing
  • Counting Bloom Filter - Bloom Filter variant that supports element removal
  • Hash Computation - Unified cryptographic hash functions (SHA-256, SHA-1, MD5, CRC32)

Requirements

  • Swift 6.2+
  • macOS 10.15+ / iOS 13.0+ / tvOS 13.0+ / watchOS 6.0+

Installation

Swift Package Manager

Add DesignAlgorithmsKit to your Package.swift:

dependencies:[.package(url:"https://github.com/rickhohler/DesignAlgorithmsKit.git", from:"1.0.0")]

Or add it via Xcode:

  1. File → Add Packages...
  2. Enter the repository URL
  3. Select version requirements

Usage

Registry Pattern

import DesignAlgorithmsKit
// Register a type
TypeRegistry.shared.register(MyType.self)
// Find registered type
iflet type =TypeRegistry.shared.find(for:"myKey"){
// Use type
}

Factory Pattern

import DesignAlgorithmsKit
// Create object via factory
letobject=tryObjectFactory.shared.create(type:"myType", configuration:[:])

Builder Pattern

import DesignAlgorithmsKit
// Build complex object
letobject=tryMyObjectBuilder().setProperty1("value1").setProperty2(42).build()

Strategy Pattern

import DesignAlgorithmsKit
// Use strategy
letstrategy:AlgorithmStrategy=ConcreteStrategy()letresult= strategy.execute(input)

Observer Pattern

import DesignAlgorithmsKit
// Subscribe to events
letobserver=MyObserver()
subject.addObserver(observer)
// Notify observers
subject.notifyObservers(event:.somethingHappened)

Queue Processing Pattern

import DesignAlgorithmsKit
// Define your item type
structMyItem:QueueItem{letid:UUIDvarstatus:QueueItemStatus=.pending
varprogress:Double=0.0letdata:Data}
// Define your processor
structMyProcessor:QueueProcessor{typealiasItem=MyItemfunc process(_ item:MyItem)asyncthrows{
// Process the item
// Update progress if needed
}}
// Create and use the queue
letqueue=ProcessingQueue<MyItem,MyProcessor>(
processor:MyProcessor(),
maxConcurrent:3)
// Add items
letitems=[MyItem(id:UUID(), data: data1),MyItem(id:UUID(), data: data2)]await queue.add(items)
// Monitor progress
letpending=await queue.pendingItems
letprocessing=await queue.processingItems
letcompleted=await queue.completedItems
letfailed=await queue.failedItems
// Retry failed items
if let failedItem =await queue.failedItems.first{await queue.retry(id: failedItem.id)}
// Pause/resume
await queue.pause()await queue.resume()

Merging/Upsert Pattern

import DesignAlgorithmsKit
// Define your item type
structMyItem:Mergeable{letid:UUIDvarname:Stringvarmetadata:[String:String]}
// Create a merger
classMyMerger:DefaultMerger<MyItem>{varstorage:[UUID:MyItem]=[:]overridefunc findExisting(by id:UUID)async->MyItem?{returnstorage[id]}overridefunc upsert(_ item:MyItem, strategy:MergeStrategy)asyncthrows->MyItem{iflet existing =awaitfindExisting(by: item.id){letmerged=merge(existing: existing, with: item, strategy: strategy)storage[item.id]= merged
return merged
}else{storage[item.id]= item
return item
}}}
// Use the merger
letmerger=MyMerger()
// Upsert with prefer existing strategy
letitem1=MyItem(id:UUID(), name:"Item", metadata:["key":"value"])letupserted1=tryawait merger.upsert(item1, strategy:.preferExisting)
// Upsert with prefer new strategy
letitem2=MyItem(id: item1.id, name:"Updated", metadata:["key":"new"])letupserted2=tryawait merger.upsert(item2, strategy:.preferNew)
// Upsert with custom merge strategy
letcustomStrategy:MergeStrategy=.custom { existing, new inletexistingItem= existing as!MyItemletnewItem= new as!MyItemvarmergedMetadata= existingItem.metadata
mergedMetadata.merge(newItem.metadata){ _, new in new }returnMyItem(
id: existingItem.id,
name: newItem.name,
metadata: mergedMetadata
)}letupserted3=tryawait merger.upsert(item2, strategy: customStrategy)

Job Manager Pattern

import DesignAlgorithmsKit
// Initialize JobManager
letjobManager=JobManager(maxConcurrentJobs:4)
// Submit a job
letjobID= jobManager.submit(description:"Heavy Processing"){
// Perform async work
tryawaitTask.sleep(nanoseconds:1*1_000_000_000)return"Success"}
// Check status (snapshot)
iflet snapshot =await jobManager.getJob(id: jobID){print("Status: \(snapshot.status)")}

Pipeline Pattern (Dynamic Async)

import DesignAlgorithmsKit
// Create a dynamic pipeline
letpipeline=DynamicAsyncPipeline()
// Add generic stages
pipeline.append(AnyAsyncPipelineStage(process:{ input inguardlet text = input as?Stringelse{throwPipelineError.invalidInputType(expected:"String", actual:"Unknown")}return text.uppercased()}))
// Execute
letresult=tryawait pipeline.execute(input:"hello world")
// Result: "HELLO WORLD"

Merkle Tree

import DesignAlgorithmsKit
// Build Merkle tree from data
letdata=["block1","block2","block3","block4"].map{ $0.data(using:.utf8)! }lettree=MerkleTree.build(from: data)
// Get root hash
letrootHash= tree.rootHash
// Generate proof for a specific leaf
iflet proof = tree.generateProof(for:data[0]){
// Verify proof
letisValid=MerkleTree.verify(proof: proof, rootHash: rootHash)}

Bloom Filter

import DesignAlgorithmsKit
// Create Bloom Filter with expected capacity and false positive rate
letfilter=BloomFilter(capacity:1000, falsePositiveRate:0.01)
// Add elements
filter.insert("element1")
filter.insert("element2")
filter.insert("element3")
// Check membership
if filter.contains("element1"){
// Element might be in set (could be false positive)
}if !filter.contains("element4"){
// Element is definitely NOT in set
}
// Use Counting Bloom Filter for removable elements
letcountingFilter=CountingBloomFilter(capacity:1000, falsePositiveRate:0.01)
countingFilter.insert("item1")
countingFilter.remove("item1")

Hash Computation

import DesignAlgorithmsKit
// Compute SHA256 hash
letdata="Hello, World!".data(using:.utf8)!
lethash=tryHashComputation.computeHash(data: data, algorithm:.sha256)
// Get hash as hex string
lethexHash=tryHashComputation.computeHashHex(data: data, algorithm:.sha256)
// Result: "dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f"
// Use string algorithm names
letsha1Hash=tryHashComputation.computeHashHex(data: data, algorithm:"sha1")
// Convenience Data extensions
letquickHash= data.sha256Hex
// Supported algorithms: SHA-256, SHA-1, MD5, CRC32
letmd5=tryHashComputation.computeHashHex(data: data, algorithm:.md5)letcrc=HashComputation.computeCRC32(data: data)

Architecture

DesignAlgorithmsKit is organized into modules:

  • Core - Base protocols and types
  • Creational - Creational design patterns
  • Structural - Structural design patterns
  • Behavioral - Behavioral design patterns
  • Algorithms - Algorithms and data structures
    • DataStructures - Merkle Tree and other data structures
    • Cryptography - Hash computation (SHA-256, SHA-1, MD5, CRC32)
  • Modern - Modern patterns and extensions

Thread Safety

All patterns are designed with thread safety in mind:

  • NSLock - For traditional concurrency
  • Actor - For Swift concurrency (Swift 5.5+)
  • Sendable - Marked where appropriate

Documentation

You can also generate documentation locally:

swift package generate-documentation --target DesignAlgorithmsKit

License

MIT License - see LICENSE file for details

Contributing

Note: This project is currently internal-only. External contributions are not accepted at this time.

For internal contributors, please read CONTRIBUTING.md for guidelines.

Before contributing, please review:

References

About

Design patterns and algorithms kit

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages