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 (SomeConfig
và SomeDatabase
đặ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:
- Dependency Injection vs Cake Pattern by Jan Machacek
- Real World Scala: Dependency Injection by Jonas Boner
- Dependency Injection in Scala: Extending the Cake Pattern by Adam Warsky
- Scalable Component Abstractions by Martin Odersky & Matthias Zenger
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
Bạn có thể 'nhập coreComp._' để giảm nhập. – leedm777