Open-Closed Principle
- 一個軟體製品應該對於擴展是開放的,但對於修改是封閉的。
"Software modules should be open for extension, but closed for modification."
一個構想實驗
一個好的軟件架構可以將修改的程式碼減少到最低程度,甚至為 0。
Example
- Bad way:
class Rectangle {
public width: number;
public height: number;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
}
}
class Circle {
public radius: number;
constructor(radius: number) {
this.radius = radius;
}
}
class AreaCalculator {
public calculateRectangleArea(rectangle: Rectangle): number {
return rectangle.width * rectangle.height;
}
public calculateCircleArea(circle: Circle): number {
return Math.PI * (circle.radius * circle.radius);
}
}
- Good way: add an interface called Shape
interface Shape {
calculateArea(): number;
}
class Rectangle implements Shape {
public width: number;
public height: number;
constructor(width: number, height: number) {
this.width = width;
this.height = height;
}
public calculateArea(): number {
return this.width * this.height;
}
}
class Circle implements Shape {
public radius: number;
constructor(radius: number) {
this.radius = radius;
}
public calculateArea(): number {
return Math.PI * (this.radius * this.radius);
}
}
class AreaCalculator {
public calculateArea(shape: Shape): number {
return shape.calculateArea();
}
}
Example 2
- Open–Closed Principle in Functional TypeScript
function Button({ text }: ButtonProps) {
return <button>{text}</button>;
}
function App() {
return <Button text='Click me!' />;
}
function Button({ text, isLoading }: ButtonProps) {
if (isLoading) {
return <svg>...</svg>;
}
return <button>{text}</button>;
}
function App() {
return <Button text='Click me!' isLoading={true} />;
}
function Loading({ isLoading, children }: LoadingProps) {
return isLoading ? <svg>...</svg> : children;
}
function Button({ text }: ButtonProps) {
return <button>{text}</button>;
}
function App() {
return (
<Loading isLoading={true}>
<Button text='Click me!' />
</Loading>
);
}