Chain of responsibility refers to behavioral design patterns.
The film company Ja-pictures shot a documentary about communist Rastafarians from Liberia called “Red Dawn of Marley”. The film is very long (8 hours), interesting, but before sending it to distribution, it turned out that in some countries, frames and phrases from the film may be considered heresy and not give a distribution license. The producers of the film decide to cut out moments containing questionable phrases from the film, manually and automatically. Double checking is necessary so that the distributor’s representatives are not simply shot in some countries, in case of an error during manual viewing and editing.
Countries are divided into four groups – countries without censorship, with moderate, medium and very strict censorship. A decision is made to use neural networks to classify the level of heresy in the review fragment of the film. Very expensive state-of-art neural networks trained for different levels of censorship are purchased for the project, the developer’s task is to break the film into fragments and pass them along a chain of neural networks, from free to strict, until one of them detects heresy, then the fragment is transferred for manual review for further editing. It is impossible to go through all the neural networks, since too much computing power is spent on their work (we still have to pay for electricity), it is enough to stop at the first one that worked.
Naive pseudocode implementation:
import StateOfArtCensorshipHLNNClassifiers
protocol MovieCensorshipClassifier {
func shouldBeCensored(movieChunk: MovieChunk) -> Bool
}
class CensorshipClassifier: MovieCensorshipClassifier {
let hnnclassifier: StateOfArtCensorshipHLNNClassifier
init(_ hnnclassifier: StateOfArtCensorshipHLNNClassifier) {
self.hnnclassifier = hnnclassifier
}
func shouldBeCensored(_ movieChunk: MovieChunk) -> Bool {
return hnnclassifier.shouldBeCensored(movieChunk)
}
}
let lightCensorshipClassifier = CensorshipClassifier(StateOfArtCensorshipHLNNClassifier("light"))
let normalCensorshipClassifier = CensorshipClassifier(StateOfArtCensorshipHLNNClassifier("normal"))
let hardCensorshipClassifier = CensorshipClassifier(StateOfArtCensorshipHLNNClassifier("hard"))
let classifiers = [lightCensorshipClassifier, normalCensorshipClassifier, hardCensorshipClassifier]
let movie = Movie("Red Jah rising")
for chunk in movie.chunks {
for classifier in classifiers {
if classifier.shouldBeCensored(chunk) == true {
print("Should censor movie chunk: \(chunk), reported by \(classifier)")
}
}
}
In general, the solution with an array of classifiers is not so bad, However! Let’s imagine that we cannot create an array, we have the ability to create only one classifier entity, which already determines the type of censorship for a fragment of the film. Such restrictions are possible when developing a library that extends the functionality of the application (plugin).
Let’s use the decorator pattern – add a reference to the next classifier in the chain to the classifier class, and stop the verification process at the first successful classification.
This way we implement the Chain of Responsibility pattern:
import StateOfArtCensorshipHLNNClassifiers
protocol MovieCensorshipClassifier {
func shouldBeCensored(movieChunk: MovieChunk) -> Bool
}
class CensorshipClassifier: MovieCensorshipClassifier {
let nextClassifier: CensorshipClassifier?
let hnnclassifier: StateOfArtCensorshipHLNNClassifier
init(_ hnnclassifier: StateOfArtCensorshipHLNNClassifier, nextClassifier: CensorshipClassifiers?) {
self.nextClassifier = nextClassifier
self.hnnclassifier = hnnclassifier
}
func shouldBeCensored(_ movieChunk: MovieChunk) -> Bool {
let result = hnnclassifier.shouldBeCensored(movieChunk)
print("Should censor movie chunk: \(movieChunk), reported by \(self)")
if result == true {
return true
}
else {
return nextClassifier?.shouldBeCensored(movieChunk) ?? false
}
}
}
let censorshipClassifier = CensorshipClassifier(StateOfArtCensorshipHLNNClassifier("light"), nextClassifier: CensorshipClassifier(StateOfArtCensorshipHLNNClassifier("normal", nextClassifier: CensorshipClassifier(StateOfArtCensorshipHLNNClassifier("hard")))))
let movie = Movie("Red Jah rising")
for chunk in movie.chunks {
censorshipClassifier.shouldBeCensored(chunk)
}
References
https://refactoring.guru/ru/ design-patterns/chain-of-responsibility
Source Code
https://gitlab.com/demensdeum/patterns/< /p>