2012-04-20 31 views
6

Tôi muốn sử dụng Mẫu bánh để tách các phần của một số hệ thống phần mềm thành các thành phần để làm cho nó hoàn toàn theo mô đun như được đề xuất trong this article. Trong trường hợp đơn giản nhất, tôi muốn có một số thành phần có thể mô phỏng, hãy nói Ghi nhật ký, Cấu hình, Cơ sở dữ liệu, Tập lệnh, vv có khả năng có thể sử dụng lẫn nhau. Các mã có thể trông giống nhưScala Cake Pattern: Chia thành phần lớn thành các tệp riêng biệt

trait AbstractConfig { 
    def config: AbstractConfigInterface 
    trait AbstractConfigInterface { 
    def test: Unit 
    } 
} 

trait SomeConfig extends AbstractConfig { 
    this: Core => 
    def config = SomeConfigImplementation 
    object SomeConfigImplementation extends AbstractConfigInterface { 
    def test = println("conf.test method called") 
    } 
} 

trait AbstractDatabase { 
    def database: AbstractDatabaseInterface 
    trait AbstractDatabaseInterface { 
    def connect: Unit 
    } 
} 

trait SomeDatabase extends AbstractDatabase { 
    this: Core => 
    def database = SomeDatabaseImplementation 
    object SomeDatabaseImplementation extends AbstractDatabaseInterface { 
    def connect = { 
     println("connect method called") 
     core.conf.test 
    } 
    } 
} 

trait Core { 
    this: AbstractDatabase with AbstractConfig => 
    def core = CoreInterface 
    object CoreInterface { 
    def db = database 
    def conf = config 
    } 
} 

object app extends Core with SomeDatabase with SomeConfig 

object Run { 
    def main(args: Array[String]) = { 
    app.core.db.connect 
    } 
} 

Đây là cơ sở dữ liệu và cấu hình các thành phần (SomeConfigSomeDatabase đặc điểm) là cắm và có thể được thay đổi để một số hiện thực khác nếu bao giờ cần thiết. Việc triển khai của họ có quyền truy cập vào đối tượng core chứa cả cơ sở dữ liệu và cấu hình, vì vậy cơ sở dữ liệu có thể truy cập cấu hình nếu cần và ngược lại. Vì vậy, câu hỏi là: Nếu bao giờ một số đặc điểm như SomeDatabase trở nên lớn và không phù hợp với một tệp duy nhất làm thế nào để tách nó thành các lớp riêng biệt giữ lại quyền truy cập đối tượng core? Để cụ thể hơn, chúng ta hãy nói rằng tôi cần phải di chuyển một số mã ra khỏi phương thức connect trong SomeDatabase vào tập tin khác:

// SomeDatabase.scala 
trait SomeDatabase extends AbstractDatabase { 
    this: Core => 
    def database = SomeDatabaseImplementation 
    object SomeDatabaseImplementation extends AbstractDatabaseInterface { 
    def connect = { 
     val obj = new SomeClass() 
    } 
    } 
} 

// SomeClass.scala in the same package 
class SomeClass { 
    core.conf.test // Does not compile - how to make it work?? 
} 

SomeClass là chi tiết thực hiện các công trình như thế nào SomeDatabase, vì vậy tôi rõ ràng là không muốn làm cho nó một đặc điểm và trộn nó vào ứng dụng. Có cách nào để cung cấp quyền truy cập vào đối tượng core cho SomeClass không?


Một số liên kết có liên quan:

  1. Dependency Injection vs Cake Pattern by Jan Machacek
  2. Real World Scala: Dependency Injection by Jonas Boner
  3. Dependency Injection in Scala: Extending the Cake Pattern by Adam Warsky
  4. Scalable Component Abstractions by Martin Odersky & Matthias Zenger

Trả lời

2

Điều đơn giản nhất để làm sẽ là để chuyển Core vào làm tham số hàm tạo cho SomeClass.

// SomeDatabase.scala 
trait SomeDatabase extends AbstractDatabase { 
    this: Core => 
    def database = SomeDatabaseImplementation 
    object SomeDatabaseImplementation extends AbstractDatabaseInterface { 
    def connect = { 
     val obj = new SomeClass(SomeDatabase.this) // pass it here 
    } 
    } 
} 

// SomeClass.scala in the same package 
class SomeClass(coreComp: Core) { // use it here 
    coreComp.core.conf.test 
} 

Điều thú vị là, tôi thực sự chỉ muốn vượt qua CoreInterface hay AbstractConfigInterface, nhưng thực tế rằng họ là loại bên trong thực sự làm điều đó khó khăn.

+0

Dave, cảm ơn câu trả lời. Cho đến nay nó có vẻ là cách hợp lý duy nhất. Điều duy nhất tôi không hiểu về nó là sự cần thiết phải gõ 'coreComp.' trong mỗi lời gọi của bất kỳ phương thức cốt lõi nào. Thật không may có vẻ như không phải là một tùy chọn để làm việc trực tiếp với 'CoreInterface', đúng không? – nab

+1

Bạn có thể 'nhập coreComp._' để giảm nhập. – leedm777

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