Skip to content

Instantly share code, notes, and snippets.

@LemonyPie
Last active December 3, 2020 20:33
Show Gist options
  • Save LemonyPie/80756e1c0662c5b33ef9a018acff204d to your computer and use it in GitHub Desktop.
Save LemonyPie/80756e1c0662c5b33ef9a018acff204d to your computer and use it in GitHub Desktop.
OOP design solution for FizzBuzz
interface Value<T> {
value: T;
}
interface Condition {
isFulfilled<T>(target: T): boolean;
}
interface Collection {
find<T, K>(target: T, defaultValue: K): K;
}
interface Rule {
isMatch<T>(target: T): boolean;
}
class Printer<T> {
constructor(
private context: Value<T>
) { }
public static print<T>(context: Value<T>): void {
console.log(context.value);
}
public print(): void {
Printer.print(this.context)
}
}
class Tag implements Value<string> {
constructor(
public readonly value: string
) { }
}
class DivisionCondition implements Condition {
constructor(
private divider: number
) { }
public isFulfilled(target: number): boolean {
return target % this.divider === 0;
}
}
class AllRequiredStrategy implements Condition {
constructor(
private validators: Condition[]
) { }
public isFulfilled<T>(target: T): boolean {
for(let validator of this.validators) {
if (!validator.isFulfilled(target)) {
return false;
}
}
return true;
}
}
class TagNumberRule<T> implements Rule {
constructor(
public tag: Value<T>,
private strategy: Condition,
) { }
public isMatch<T>(target: T): boolean {
return this.strategy.isFulfilled(target);
}
}
class TagNumberRules<T> implements Collection {
constructor(
private rules: TagNumberRule<T>[]
) { }
public find<K>(value: K, defaultValue: Value<T>): Value<T> {
for(let rule of this.rules) {
if (rule.isMatch(value)) {
return rule.tag;
}
}
return defaultValue;
}
}
const numberTags = new TagNumberRules([
new TagNumberRule(new Tag('FizzBuzz'), new AllRequiredStrategy([new DivisionCondition(3), new DivisionCondition(5)])),
new TagNumberRule(new Tag('Fizz'), new AllRequiredStrategy([new DivisionCondition(3)])),
new TagNumberRule(new Tag('Buzz'), new AllRequiredStrategy([new DivisionCondition(5)]))
])
for(let i = 0; i < 100; i++) {
Printer.print(numberTags.find(i, new Tag(i.toString())))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment