gpt4 book ai didi

Java数据库驱动设计

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:11:45 25 4
gpt4 key购买 nike

我遇到这个问题,我需要设计一个 Java 包用于:

  • 从不同的数据源获取数据。例如,A 类将从 Oracle 数据库中检索客户数据,而 B 类将从 Web 服务数据源中检索相同的信息(通过 SOAP )。
  • 结果需要合并,合并的规则非常复杂,所以理想情况下我应该对这个包的用户(其他开发人员)隐藏它。
  • 当一个数据源失败时,我仍然需要从其他数据源返回结果。但是,我还需要让调用者知道其中一个数据源未能响应。

现在,我正在通过在 A 类和 B 类中设置一个 boolean 值来指示是否存在错误,以及另一个用于存储实际错误消息的对象。调用者必须在调用后检查此 boolean 值以查看是否发生错误。

什么是好的设计模型?

最佳答案

答案会非常广泛,所以我建议您使用:

此伪代码的语法与 UML 相似和 Python :

// The data implements one interface
Data {interface}

// And you implement it with DatabaseData
DbData -> Data
...

// Or WebServiceData
WsData -> Data
...

// -- DAO part
Dao {interface}
+ fetch(): Data[]

// From database
DatabaseDao -> Dao
- data: Data[0..*]
// Query database and create dbData from rows...
+ fetch(): Data[]
self.status = "Not ok"
self.status = connectToDb()
if( self.status == ok ,
performQuery()
forEach( row in resultSet,
data.add( DbData.new( resultSet.next() ) )
)
disconnect()
)
...

// From web service
WebServiceDao -> Dao
- data: Data[0..*]
// Execute remote method and create wsData from some strange object
+ fetch(): Data[]
remoteObject: SoapObject = SoapObject()
remoteObject.connect()
if (remoteObject.connected?(),
differentData: StrangeObject = remoteObject.getRemoteData()
forEach( object in differentData ,
self.data.add( WsData.new( fromElement ))
)
).else(
self.status = "Disconnected"
)
....
// -- State part
// Abstract the way the data is going to be retrieved
// either from two sources or from a single one.
FetcheState { abstract }

- context: Service
- dao: Dao // Used for a single source

+ doFetch(): Data[] { abstract }

+ setContext( context: Service )
self.context = context
+ setSingleSource( dao: Dao)
self.dao = dao

// Fetches only from one DAO, and it doesn't quite merge anything
// because there is only one source after all.
OneSourceState -> FetcheState
// Use the single DAO and fetch
+ doFetch(): Data[]
data: Data[] = self.dao.doFetch()
// It doesn't hurt to call "context's" merger anyway.
context.merger.merge( data, null )

// Two sources, are more complex, fetches both DAOs, and validates error.
// If one source had an error, it changes the "state" of the application (context),
// so it can fetch from single source next time.
TwoSourcesState -> FetcheState
- db: Dao = DatabaseDao.new()
- ws: Dao = WebServiceDao.new()

+ doFetch(): Data[]
dbData: Data[] = db.doFetch()
wsData: Data[] = ws.doFetch()

if( ws.hadError() or db.hadError(),
// Changes the context's state
context.fetcher = OneSourceState.new()
context.merger = OneKindMergeStrategy.new()
context.fetcher.setContext( self.context )
// Find out which one was broken
if( ws.hadError(),
context.fetcher.setSingleSource( db )
)
if( db.hadError(),
context.fetcher.setSingleSource( ws )
)
)
// Since we have the data already let's
// merge it with the "context's" merger.
return context.merger.merge( dbData, wsData)

// -- Strategy part --
// Encapsulate algoritm to merge data
Strategy{ interface }
+ merge( a: Data[], with : Data[] )

// One kind doesn't merge too much, just "cast" one array
// because there is only one source after all.
OneKindMergeStrategy -> Strategy
+ merge( a: Data[], b: Data[] )
mergedData: Data[]
forEach( item, in( a ),
mergedData = Data.new( item ) // Take values from wsData or dbData
)
return mergedData

// Two kinds merge, encapsulate the complex algorithm to
// merge data from two sources.
TwoKindsMergeStrategy -> Strategy
+ merge( a: Data[], with: Data[] ): Data[]
forEach( item, in( a ),
mergedData: Data[]
forEach( other, in(with ),
WsData wsData = WsData.cast( item )
DbData dbData = DbData.cast( other )
// Add strange and complex logic here.
newItem = Data.new()
if( wsData.name == dbData.column.name and etc. etc ,
newItem.name = wsData+dbData...e tc. etc
...
mergedData.add( newItem )
)
)
)
return mergedData

// Finally, the service where the actual fetch is being performed.
Service { facade }

- merger: Strategy
- fetcher: FetcheState

// Initialise the object with the default "strategy" and the default "state".
+ init()
self.fetcher = TwoSourcesState()
self.merger = TwoKindsMergeStrategy()
fetcher.setContext( self )

// Nahh, just let the state do its work.
+ doFetch(): Data[]
// Fetch using the current application state
return fetcher.doFetch()

客户端使用:

     service: Service = Service.new()
service.init()
data: Data[] = service.doFetch()

不幸的是,它看起来有点复杂。

OOP 在很大程度上基于多态性。

所以在 Dao 中,您让子类从任何地方获取数据,您只需将其称为 dao.fetch()。

Strategy 中相同,子类执行一种算法或另一种算法(避免有很多奇怪的 ifelse的,switch 等)。

使用 State 会发生同样的事情。而不是像这样:

if isBroken and itDoesntWork() and if ImAlive()

等等,等等。你只是说,“嘿,这将是代码一。有两个连接,这是只有一个的时候。”。

最后,facade 对客户说“别担心,我来处理。”。

关于Java数据库驱动设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2098753/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com