🧪 Tapşırıq
Aşağıdakı kod nümunəsində Shape adlı əsas class-dan Square və Triangle class-ları yaradılır. Hər forma həm Vector (xəttlərlə) həm də Raster (piksel ilə) şəklində çəkilə bilər. Bu isə hər formanın iki fərqli versiyasının yaradılmasına səbəb olur:
class Shape {
constructor(name) {
this.name = name;
}
}
class Triangle extends Shape {
constructor() {
super('triangle');
}
}
class Square extends Shape {
constructor() {
super('square');
}
}
class VectorSquare extends Square {
toString() {
return 'Drawing square as lines';
}
}
class RasterSquare extends Square {
toString() {
return 'Drawing square as pixels';
}
}
// imagine VectorTriangle and RasterTriangle are here too
Bu yanaşma çox sayda class-ın yaradılmasına səbəb olur və sistemin genişləndirilməsini çətinləşdirir. Hər yeni forma və render üsulu üçün yeni bir class əlavə etmək lazım gəlir. Bu, məhz Dekart hasili problemini yaradır:
Formalar × Render üsulları = Çox sayda sinif
Yuxarıdakı kodu elə refactor edin ki, Bridge Pattern-dən istifadə edərək VectorTriangle və RasterTriangle yaradıb kodu new Triangle(new RasterRenderer()); formada çağırdıqda cavabında Drawing Triangle as pixels alınsın.
🧩 Həlli
Çalışın ilk öncə özünüz həll edin sonra həllinə baxın
Spoiler
Bu problemi Bridge Pattern ilə həll edə bilərik. Bu dizayn pattern-in məqsədi abstraksiyanı onun implementasiyasından ayırmaqdır. Bununla da hər iki tərəf müstəqil şəkildə inkişaf etdirilə bilər.
// Renderer interfeysini təmsil edən baza class
class Renderer {
get whatToRenderAs() {
throw new Error('whatToRenderAs not implemented');
}
}
// Konkret Renderer-lər
class VectorRenderer extends Renderer {
get whatToRenderAs() {
return 'lines';
}
}
class RasterRenderer extends Renderer {
get whatToRenderAs() {
return 'pixels';
}
}
// Baz forma classı— artıq rendereri qəbul edir
class Shape {
constructor(name, renderer) {
this.name = name;
this.renderer = renderer;
}
toString() {
return `Drawing ${this.name} as ${this.renderer.whatToRenderAs}`;
}
}
// Konkret formalar — yalnız ad və renderer qəbul edir
class Triangle extends Shape {
constructor(renderer) {
super('Triangle', renderer);
}
}
class Square extends Shape {
constructor(renderer) {
super('Square', renderer);
}
}
️ İstifadə nümunəsi
const triangle = new Triangle(new RasterRenderer());
console.log(triangle.toString());
// Output: Drawing Triangle as pixels
const square = new Square(new VectorRenderer());
console.log(square.toString());
// Output: Drawing Square as lines