浅谈JavaScript 代码简洁之道(10)

Good:

class Shape {
 setColor(color) {
 // ...
 }

 render(area) {
 // ...
 }
}

class Rectangle extends Shape {
 constructor(width, height) {
 super();
 this.width = width;
 this.height = height;
 }

 getArea() {
 return this.width * this.height;
 }
}

class Square extends Shape {
 constructor(length) {
 super();
 this.length = length;
 }

 getArea() {
 return this.length * this.length;
 }
}

function renderLargeShapes(shapes) {
 shapes.forEach((shape) => {
 const area = shape.getArea();
 shape.render(area);
 });
}

const shapes = [new Rectangle(4, 5), new Rectangle(4, 5), new Square(5)];
renderLargeShapes(shapes);

接口隔离原则

JavaScript 几乎没有接口的概念,所以这条原则很少被使用。官方定义是“客户端不应该依赖它不需要的接口”,也就是接口最小化,把接口解耦。

Bad:

class DOMTraverser {
 constructor(settings) {
 this.settings = settings;
 this.setup();
 }

 setup() {
 this.rootNode = this.settings.rootNode;
 this.animationModule.setup();
 }

 traverse() {
 // ...
 }
}

const $ = new DOMTraverser({
 rootNode: document.getElementsByTagName('body'),
 animationModule() {} // Most of the time, we won't need to animate when traversing.
 // ...
});

Good:

class DOMTraverser {
 constructor(settings) {
 this.settings = settings;
 this.options = settings.options;
 this.setup();
 }

 setup() {
 this.rootNode = this.settings.rootNode;
 this.setupOptions();
 }

 setupOptions() {
 if (this.options.animationModule) {
  // ...
 }
 }

 traverse() {
 // ...
 }
}

const $ = new DOMTraverser({
 rootNode: document.getElementsByTagName('body'),
 options: {
 animationModule() {}
 }
});

依赖反转原则

说就两点:

  1. 高层次模块不能依赖低层次模块,它们依赖于抽象接口。
  2. 抽象接口不能依赖具体实现,具体实现依赖抽象接口。

总结下来就两个字,解耦。

Bad:

// 库存查询
class InventoryRequester {
 constructor() {
 this.REQ_METHODS = ['HTTP'];
 }

 requestItem(item) {
 // ...
 }
}

// 库存跟踪
class InventoryTracker {
 constructor(items) {
 this.items = items;

 // 这里依赖一个特殊的请求类,其实我们只是需要一个请求方法。
 this.requester = new InventoryRequester();
 }

 requestItems() {
 this.items.forEach((item) => {
  this.requester.requestItem(item);
 });
 }
}

const inventoryTracker = new InventoryTracker(['apples', 'bananas']);
inventoryTracker.requestItems();

Good:

// 库存跟踪
class InventoryTracker {
 constructor(items, requester) {
 this.items = items;
 this.requester = requester;
 }

 requestItems() {
 this.items.forEach((item) => {
  this.requester.requestItem(item);
 });
 }
}

// HTTP 请求
class InventoryRequesterHTTP {
 constructor() {
 this.REQ_METHODS = ['HTTP'];
 }

 requestItem(item) {
 // ...
 }
}

// webSocket 请求
class InventoryRequesterWS {
 constructor() {
 this.REQ_METHODS = ['WS'];
 }

 requestItem(item) {
 // ...
 }
}

// 通过依赖注入的方式将请求模块解耦,这样我们就可以很轻易的替换成 webSocket 请求。
const inventoryTracker = new InventoryTracker(['apples', 'bananas'], new InventoryRequesterHTTP());
inventoryTracker.requestItems();


      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/90.html