Вопрос о Cake Pattern - PullRequest
       13

Вопрос о Cake Pattern

6 голосов
/ 15 апреля 2011

Пусть есть несколько отдельных классов DAO OrderDAO, ProductDAO и CustomerDAO, которые хранят / извлекают данные в базе данных и совместно используют один экземпляр DataSource (фабрика соединений с базой данных).

Чтобы создать экземпляр DataSource и подключить его к DAOs, мы обычно используем Spring DI.Теперь я хотел бы сделать это в Scala без какой-либо инфраструктуры DI.

Я читал о шаблоне тортов , и похоже, что я должен сделать следующее:

trait DatabaseContext { val dataSource:Datasource }

trait OrderDAO {this:DatabaseContext =>
  ... // use dataSource of DatabaseContext
}

trait ProductDAO {this:DatabaseContext => 
  ... // use dataSource of DatabaseContext
}

object DAOImpl extends OrderDAO with ProductDAO with DatabaseContext {
  val dataSource = ... // init the data source
}

Правильно ли я понимаю структуру торта?

Могу ли я реализовать эти DAOs по-разному, используя шаблон тортов?

Что это обеспечивает, что структуры DI, такие как Spring, не делают?

Как создать отдельное OrderDAOImpl и ProductDAOImpl объекты, совместно использующие один DataSource экземпляр вместо одного большого DAOImpl?

Ответы [ 2 ]

5 голосов
/ 02 сентября 2011

Преимущества шаблона тортов:

  • В отличие от DI-решений на основе файлов конфигурации, сопоставление контрактов с реализациями выполняется во время компиляции, что уменьшает проблемы с нахождением классов и совместимостью.Тем не менее, многие механизмы DI имеют альтернативную функцию конфигурации в коде
  • Сторонние библиотеки не используются.Самостоятельные аннотации, позволяющие использовать шаблон, являются функцией родного языка.Специальный синтаксис не используется для извлечения реализации контракта
  • Забвение указания реализации для компонента, необходимого для другого компонента, приводит к ошибке времени выполнения - просто проверьте эту статью http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di.html и попробуйте не указыватьодин из компонентов или указание черты вместо конкретного класса в любом из примеров шаблонов тортов или даже забывание инициализировать значение, соответствующее необходимому компоненту

Однако, чтобы воспользоваться этими преимуществами, вам нужночтобы более строго придерживаться архитектуры шаблона - проверьте ту же статью и обратите внимание на черты обертывания, которые содержат фактические контракты и реализации.

Ваши примеры не являются строго шаблоном торта.В вашем случае вы могли бы просто использовать наследование для создания реализаций для ваших признаков и использовать отдельные классы для каждого компонента DAO.В шаблоне «торт» потребительский код будет таким же компонентом, как и код DAO, а код, собирающий зависимости, будет отдельно от него.

Чтобы проиллюстрировать шаблон «торт», вам необходимо добавить классы потребления (слой домена или пользовательский интерфейс) к вашему примеру.Или в случае, если ваши компоненты DAO получили доступ к функциям друг друга, вы могли бы проиллюстрировать шаблон торта на одном только DAO.

, если коротко,

trait OrderDAOComponent {
    val dao: OrderDAO
    trait OrderDAO {  
        def create: Order
        def delete(id: Int): Unit  
        //etc 
    }  
}

trait OrderDAOComponentImpl extends OrderDAOComponent {  
    class OrderDAOJDBCImpl extends OrderDAO {  
        def create: Order = {/*JDBC-related code here*/}
        def delete(id: Int) {/*JDBC-related code here*/}
        //etc
    }  
}  

//This one has a dependency
trait OrderWebUIComponentImpl {  
    this: OrderDAOComponent =>  
    class OrderWebUI {  
        def ajaxDelete(request:HttpRequest) = {  
            val id = request.params("id").toInt
            try {
                dao.delete(id)
                200
            }
            catch {
                case _ => 500
            }

        }  
    }  
}  

//This matches contracts to implementations

object ComponentRegistry extends  
    OrderDAOComponentImpl with  
    OrderWebUIComponentImpl
{  
    val dao = new OrderDAOJDBCImpl
    val ui = new OrderWebUI
}  

//from some front-end code
val status = ComponentRegistry.ui.ajaxDelete(request)

Подробнее на вашем примере.Я думаю, что это может быть больше похоже на торт, если:

trait DatabaseContext { val dataSource:Datasource }

trait OrderDAOComponent {this:DatabaseContext =>
    trait OrderDAOImpl {
        ... // use dataSource of DatabaseContext
    }
}

trait ProductDAOComponent {this:DatabaseContext => 
    trait ProductDAOImpl {
        ... // use dataSource of DatabaseContext
    }
}

object Registry extends OrderDAOComponent with ProductDAOComponent with DatabaseContextImpl {
    val dataSource = new DatasourceImpl //if Datasource is a custom trait, otherwise wrapping needed
    val orderDAO = new OrderDAOImpl
    val productDAO = new ProductDAOImpl
}

//now you may use them separately
Registry.orderDAO.//
2 голосов
/ 15 апреля 2011

Может быть:

  • Статически проверяется во время компиляции.
...