2012-04-13 38 views
6

Tôi đã tạo một lớp đơn mà tôi muốn mở rộng. Nó (một nửa) hoạt động ở chỗ nó chỉ tạo ra một cá thể của lớp, nhưng các thuộc tính được thêm vào lớp con là không xác định. Đây là singleton gốc:Cách tạo lớp con coffeescript singleton

class Singleton 
    _instance = undefined 
    @getInstance: -> 
     if _instance is undefined 
     console.log 'no instance exists, so create one' 
     _instance = new _Singleton() 
     else 
     console.log 'an instance already exists.' 

class _Singleton 
    constructor: -> 
     console.log 'new singelton' 

module.exports = Singleton 

Và đây là lớp con:

Singleton = require('./singleton') 

class Stinky extends Singleton 
     constructor: -> 
     var1 : 'var1' 


module.exports = Stinky 

Bây giờ nếu tôi sử dụng những điều sau đây trong ứng dụng nút của tôi:

Stinky = require './stinky' 
thing1 = Stinky.getInstance() 
thing2 = Stinky.getInstance() 
console.log "Thing var1: #{thing1.var1}" 

phương pháp getInstance() xử như mong đợi, nhưng var1 là không xác định. Nếu tôi làm điều tương tự trên các lớp không singleton họ làm việc tốt. Cảm ơn.

+1

Có phải 'var1: 'var1'' là lỗi đánh máy không? Nếu nó là 'var1 = 'var1'' hoặc thực sự' @ var1 =' var1''? – Sandro

Trả lời

2

Tôi thấy cách bạn đang sử dụng lớp học _Singleton để cố gắng mô phỏng một lớp riêng tư, nhưng rất tiếc, tôi không nghĩ bạn có thể sử dụng nó trong trường hợp này.

Dưới đây là một số mã mà làm việc:

class Singleton 
    _instance = undefined 

    constructor: -> 
     console.log 'new singleton' 

    @getInstance: -> 
     if _instance is undefined 
     console.log 'no instance exists, so create one' 
     _instance = new @() 
     else 
     console.log 'an instance already exists.' 
     _instance 

class Stinky extends Singleton 
     constructor: -> 
     console.log 'Stinky constructor' 
     @var1 = 'var1' 


thing1 = Stinky.getInstance() 
thing2 = Stinky.getInstance() 

console.log "Thing var1: #{thing1.var1}"​​​​​​​​​​​​​​​​​​, thing1, thing2​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​ 

tôi loại bỏ các Node.js (yêu cầu) mã, nhưng thêm vào đó nên đơn giản. Sự khác biệt chính là trường hợp mã của tôi đang tạo là một phiên bản của @ hoặc this. Làm như vậy sẽ đảm bảo hàm tạo của bạn được gọi đầu tiên sau đó tiếp tục chuỗi gốc. Mã của bạn đã tạo một thể hiện rõ ràng là _Singleton vì vậy hàm tạo Stinky của bạn chưa bao giờ được gọi. Một vấn đề nhỏ khác mà bạn cuối cùng cũng nhận thấy là phương pháp getInstance của bạn không thực sự trở về một thể hiện của _instance.

Tôi hy vọng điều này sẽ giúp,

Sandro

+0

Cảm ơn Sandro. Sẽ cho nó một bash. –

12

Tôi tỉa mã của bạn xuống một chút. Dưới đây là 2 lớp còn lại:

class Singleton 
    @_instance: null 
    @getInstance: -> 
    @_instance or= new @(arguments...) 

class Stinky extends Singleton 
    constructor: (@num) -> 

thing1 = Stinky.getInstance(1) 
thing2 = Stinky.getInstance(2) 

console.log(thing1.num, thing2.num) 

tôi đã thực hiện những thay đổi sau:

  • Merged Singleton và _Singleton
  • _instance Đã đổi @_instance để nó sẽ được gắn vào Singleton chứ không phải là nguyên mẫu của nó
  • Thêm đối số splat trong getInstance (trong trường hợp đối số là cần thiết)
  • trỏ getInstance() vào đối tượng mở rộng thay vì Singleton

Trong ví dụ này, tôi đã sử dụng 2 số khác nhau để đảm bảo rằng hàm tạo thứ 2 không bao giờ được gọi.

1

Tôi không chắc chắn những gì mục tiêu là, nhưng bạn có thể đạt được kết quả tương tự bằng cách làm cho Singleton một singleton thực (một đối tượng đơn giản):

Singleton = 
    doNothing: -> 
     # ... 
    doMoreNothing: -> 
     # ... 

class Stinky 
    constructor: -> 
     @var1: 'var1' 
    getInstance: -> 
     return Singleton 

Nó không có ý nghĩa nhiều đối với Singleton để có một phương thức tự trả về.

+0

Đây là câu trả lời đúng cho phong cách Coffeescript (và Javascript) thực sự. Javascript là một ngôn ngữ dựa trên nguyên mẫu, vì vậy các mẫu thiết kế OOP phổ biến như Singleton không có ý nghĩa. – Vortico

+0

@Vortico Tôi không đồng ý. Thực tế là CoffeeScript có một từ khóa 'class' cho bạn biết rằng nó nhằm mục đích mô phỏng một mô hình thừa kế dựa trên lớp quen thuộc hơn. Coffeebook Cookbook duy trì cộng đồng thậm chí có [trang trên mẫu Singleton] (http://coffeescriptcookbook.com/chapters/design_patterns/singleton). Đáng buồn thay, trang không đề cập đến thừa kế. :( –

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