2017-12-18 100 views
7

Tôi có một hệ thống phân cấp lớp như:Node.js - tạo đối tượng của tên lớp theo quy định tại biến

   |-> Square 
AbstractShape -+-> Circle 
       |-> Triangle 

Bây giờ, tôi muốn thực hiện mô hình chiến lược và tạo ra một đối tượng của lớp đó được lưu trữ trong chuỗi. Trong PHP tôi muốn sử dụng:

$type = 'Square'; 
$obj = new $type(); 

Có tương đương trong Node.js không?

+0

giống như gọi 'Quảng trường mới()' – zabusa

Trả lời

4

Nếu bạn đang có nhu cầu đi với một cách tiếp cận mạnh mẽ hơn và kiểm chứng, bạn có thể sử dụng kết hợp các lớp và mẫu nhà máy để phát hành đối tượng. Kiểm tra những điều sau, bạn sẽ thấy rằng với thiết lập này, bao gồm logic chi tiết hơn và thử nghiệm xuống con đường sẽ trở nên dễ dàng hơn và đủ khả năng bạn linh hoạt hơn. Bạn cũng đang trừu tượng hóa việc tự tìm đối tượng mới sau cuộc gọi .issue - điều này có thể mang lại lợi ích và thuận tiện trong một số trường hợp.

Tôi cũng lưu ý rằng bạn đề cập đến nền PHP của bạn, vì vậy tôi cũng giới thiệu một chút về cách tiếp cận đối tượng được định hướng có thể được thực hiện trong ES6.

class AbstractShape { 
    constructor(type) { 
    this.type = type; 
    } 

    getType() { 
    console.log(`I am a ${this.type}`); 
    } 
} 

class Square extends AbstractShape { 
    constructor(type) { 
    super(type); 
    this.sides = 4; 
    } 

    getDescription() { 
    console.log(`I have ${this.sides} equal sides`); 
    } 
} 

class ShapeFactory { 
    static issue(type) { 
    switch(type) { 
     case 'Square': return new Square(type); 
     break; 
     case 'Circle': /* same pattern with a Circle class */ 
     break; 
    } 
    } 
} 

let shape = ShapeFactory.issue('Square'); 

shape.getType();  /* I am a Square */ 
shape.getDescription(); /* I have 4 equal sides */ 

JSFiddle Link - bản demo


Hơn nữa, nếu bạn muốn một cái gì đó một chút lỗi hơn khoan dung hơn đối phó với chuỗi thừa ví dụ 'Square' - there are some creative ways để tận dụng các phương pháp giống như enum có thể tinh chỉnh điều này hơn nữa. Tôi sẽ lưu bất động sản ở đây và không băm nhỏ đoạn mã, nhưng sẽ bao gồm một fiddle cho bạn để kiểm tra.

JSFiddle Link - enum cách tiếp cận bản demo

2
  1. Cách nhanh chóng và bẩn là sử dụng eval. Nhưng đó là mạnh mẽ không được khuyến khích vì nhiều lý do - an ninh, hiệu suất, khả năng đọc, supportability

    function MyType() { 
    } 
    
    var typeName = 'MyType'; 
    var typeObj = eval('new ' + typeName + '()'); 
    
  2. an toàn hơn nhiều và chính xác hơn eval là sử dụng bản đồ của tên chuỗi các loại (nhờ @GaloisGecko)

    function createType(name) { 
        var types = { 
        "Square": Square, 
        "Circle": Circle, 
        "Triangle": Tringle 
        }; 
        return types.hasOwnProperty(name) ? new types[name]() : null; 
    } 
    
  3. Cuối cùng, quyết định tốt nhất và khôn ngoan là áp dụng mẫu Nhà máy. Xem @scniro answer. Ngoài ra, bạn có thể tìm thấy mô tả tốt và gương here

+0

Bất cứ khi nào có thể, không sử dụng 'eval'. Và ở đây bạn không cần, vì vậy hãy tránh xa giải pháp này. –

4

Một cách an toàn sẽ được xác định một đối tượng nhà máy:

function Square() { 
} 

// here other constructors for Circle and Triangle 

var factory = { 
    "Square": Square, 
    "Circle": Circle, 
    "Triangle" : Triangle 
} 

var typeName; 

// here some code which sets typeName 

var typeObj = new factory[typeName](); 
1

Sau khi xem xét chặt chẽ hơn có cách khá đơn giản xung quanh cho Node.js. Khi bạn khởi tạo một đối tượng theo cách đơn giản nhất bạn thực sự viết new <variableName> trong đó variableName là phần thân của một số hàm hoặc lớp được xác định và xuất trong một số mô-đun. Để gán hàm/lớp này cho biến bạn require() nó.

Vì vậy, thay vì

const type = 'Square'; 
const aSquare = new type(); 

bạn cần phải viết:

const type = 'Square'; 
const shape = require(`${pathToShapeModules}/${type}.js`); 
const aShape = new shape(); 

nhược điểm nhỏ là eslint mà phàn nàn (trong một số thiết lập quy tắc) mà require s phải được đặt trên đầu trang của mô-đun. Và tất nhiên nó cần xử lý ngoại lệ thích hợp bằng cách thử ... bắt vv vì vậy có lẽ giải pháp Nhà máy là tốt hơn (vì vậy tôi sẽ chấp nhận nó) nhưng tôi nghĩ rằng đối với các trường hợp chuyên ngành nhỏ giải pháp này là ok.

Các vấn đề liên quan