A Swift package providing common design patterns and algorithms with protocols and base types for extensibility.
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.
- 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
- 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
- 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
- Registry Pattern - Centralized type registration and discovery
- Provider Pattern - Chain of responsibility for extensible behavior
- Repository Pattern - Data access abstraction
- 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)
- Swift 6.2+
- macOS 10.15+ / iOS 13.0+ / tvOS 13.0+ / watchOS 6.0+
Add DesignAlgorithmsKit to your Package.swift:
dependencies:[.package(url:"https://github.com/rickhohler/DesignAlgorithmsKit.git", from:"1.0.0")]Or add it via Xcode:
- File → Add Packages...
- Enter the repository URL
- Select version requirements
import DesignAlgorithmsKit
// Register a type
TypeRegistry.shared.register(MyType.self)
// Find registered type
iflet type =TypeRegistry.shared.find(for:"myKey"){
// Use type
}import DesignAlgorithmsKit
// Create object via factory
letobject=tryObjectFactory.shared.create(type:"myType", configuration:[:])import DesignAlgorithmsKit
// Build complex object
letobject=tryMyObjectBuilder().setProperty1("value1").setProperty2(42).build()import DesignAlgorithmsKit
// Use strategy
letstrategy:AlgorithmStrategy=ConcreteStrategy()letresult= strategy.execute(input)import DesignAlgorithmsKit
// Subscribe to events
letobserver=MyObserver()
subject.addObserver(observer)
// Notify observers
subject.notifyObservers(event:.somethingHappened)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()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)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)")}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"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)}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")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)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
All patterns are designed with thread safety in mind:
- NSLock - For traditional concurrency
- Actor - For Swift concurrency (Swift 5.5+)
- Sendable - Marked where appropriate
- Full API Documentation (DocC) - Complete API reference with interactive documentation
- Design Patterns Guide
- Usage Examples
You can also generate documentation locally:
swift package generate-documentation --target DesignAlgorithmsKitMIT License - see LICENSE file for details
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: