AppFuse 模式:DAO 介面/實現、Service 介面/實現、DataObject……共 5 類。除非系統極其複雜,否則YAGNI(You Ain't Gonna Need It)。
getHibernateTemplate() 存取資料庫。當直覺覺得「必須分離 DAO 與 Service」時,再拆分不遲。
Martin Fowler 指出:強制每個類分離介面/實現是過度設計。僅在「多種實現」或「需消除實現依賴」時引入介面。
聲明式事務用 Spring AOP,預設 JDK 動態代理要求目標實現介面。
<bean class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
id="baseService" abstract="true">
<property name="transactionManager" ref="transactionManager"/>
<property name="proxyTargetClass" value="true"/> <!-- 關鍵:使用 CGLIB 代理具體類 -->
</bean>
所有 Service Bean 繼承 baseService,即可無介面編程,單例下效能無損。
| 層級 | AppFuse | 極簡模式 |
|---|---|---|
| DAO 介面 | ✅ | ❌ |
| DAO 實現 | ✅ | ❌ |
| Service 介面 | ✅ | ❌ |
| Service 實現 | ✅ | ❌ |
| DataObject | ✅ | ✅ (DO/VO) |
| Manager | ❌ | ✅ (融合 DAO+Service) |
SpringSide 專案遷就社區壓力暫時分離 DAO/Service,但堅持不寫多餘介面。善用 IDEA 代碼生成熱鍵,為 Manager 生成委派 DAO 方法,兼顧效率與結構。
Model 層應服務於業務複雜度,而非框架教條。DO + Manager 兩層走天下,若覺得太簡單,說明你的系統還不夠複雜——這是好事。