The strategy pattern decouples the client from its implementation, allowing the
client to use different algorithms interchangeably without knowing the specifics
of each algorithm’s implementation.
«
V
C
«
E
A
e
C
a
o
C
m
l
.
o
l
n
o
a
g
g
n
i
t
e
n
i
o
.
t
d
e
.
v
c
l
r
e
a
x
g
a
r
V
i
V
x
t
t
.
l
e
a
t
a
t
o
I
i
t
l
h
l
»
r
n
i
d
e
i
m
i
t
s
a
S
d
I
d
e
V
t
t
a
n
a
r
a
o
r
t
t
t
f
l
r
a
i
e
e
a
i
-
t
o
r
(
c
d
>
e
n
f
)
e
(
V
g
S
a
(
)
a
y
t
c
)
l
A
r
e
i
»
a
(
d
t
)
a
s
t
t
e
r
(
«
P
A
e
a
)
C
h
l
.
t
o
o
g
g
e
n
n
o
.
g
c
e
r
y
r
V
i
V
/
e
a
t
a
v
t
l
h
l
a
e
i
m
i
l
S
d
I
d
i
t
a
n
a
d
r
t
t
t
a
a
i
e
e
t
t
o
r
(
o
e
n
f
)
r
g
S
a
y
t
c
B
r
e
»
a
(
t
)
«
V
A
e
«
M
A
e
S
a
l
.
C
o
l
.
t
l
g
g
o
n
g
g
r
i
o
.
n
t
o
.
a
d
r
c
h
r
t
a
i
V
r
V
i
V
e
t
t
a
e
a
t
a
g
i
h
l
t
l
h
l
y
o
m
i
e
i
m
i
»
n
I
d
S
d
I
d
S
n
a
t
a
n
a
t
t
t
r
t
t
t
r
e
e
a
i
e
e
a
r
(
t
o
r
(
t
f
)
e
n
f
)
e
a
g
S
a
g
c
y
t
c
y
e
C
r
e
(
»
a
(
)
t
)
type Strategy < T > = {
validate ( value : T ) : boolean ;
algorithmInterface () : void ;
};
// ConcreteStrategyA
export class EmailValidationStrategy implements Strategy < string > {
validate ( value : string ) : boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/ . exec ( value ) !== null ;
}
algorithmInterface () : void {
console . log ( "ConcreteStrategyA" );
}
}
// ConcreteStrategyB
export class PhoneValidationStrategy implements Strategy < string > {
validate ( value : string ) : boolean {
return /^(\+?\d{1,2}[-\s]?|)(?:\d{3}[-\s]?){2}\d{4}$/ . exec ( value ) !== null ;
}
algorithmInterface () : void {
console . log ( "ConcreteStrategyB" );
}
}
// ConcreteStrategyC
export class MonthValidationStrategy implements Strategy < string > {
validate ( value : string ) : boolean {
return (
/^(Jan|Feb|March|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)$/ . exec ( value ) !==
null
);
}
algorithmInterface () : void {
console . log ( "ConcreteStrategyC" );
}
}
export class Context {
constructor ( private readonly strategy : Strategy < string >) {}
// ContextInterface(): void {
// this.strategy.algorithmInterface();
// }
validate ( value : string ) : boolean {
return this . strategy . validate ( value );
}
}
import { describe , test , expect } from "bun:test" ;
import {
Context ,
EmailValidationStrategy ,
MonthValidationStrategy ,
PhoneValidationStrategy ,
} from "./code.ts" ;
describe ( "Strategy Pattern" , () => {
test ( "should validate email" , () => {
const context = new Context ( new EmailValidationStrategy ());
const result = context . validate ( "no-reply@email.clutter" );
expect ( result ). toBe ( true );
});
test ( "should validate phone" , () => {
const context = new Context ( new PhoneValidationStrategy ());
const result = context . validate ( "123-456-7890" );
expect ( result ). toBe ( true );
});
test ( "should validate month" , () => {
const context = new Context ( new MonthValidationStrategy ());
const result = context . validate ( "Jan" );
expect ( result ). toBe ( true );
});
});