我有这个问题需要设计一个用于以下的Java包:
现在,我正在通过在A类和B类中指定是否存在错误的布尔值以及用于存储实际错误消息的另一个对象来实现此目的。调用者在调用之后必须检查此布尔值以查看是否发生了错误。
对此有什么好的设计模型?
答案 0 :(得分:6)
答案非常宽泛,所以我建议您使用:
// 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
相同的情况下,子类执行一种算法或另一种算法(以避免有很多奇怪的if
,else
,switch
' s等。)。
State
同样的事情发生了。而不是像:
if isBroken and itDoesntWork() and if ImAlive()
等等,你只是说,“嘿,这将是代码一。有两个连接,这是只有一个。”。
最后,门面对客户说:“别担心,我会处理这个。”。
答案 1 :(得分:1)
您需要编写解决方案,还是需要解决方案?有很多免费的Java软件可以完成这些工作 - 为什么要重新发明轮子。参见:
答案 2 :(得分:0)
我建议一个Facade代表整个对象(客户数据)和一个工厂,它通过从每个数据源检索并将它们传递给Facade(在构造函数中或作为构建器,依赖于有多少)。具有特定数据源的单个类将具有一个方法(在公共接口或基类上),以指示检索数据时是否存在错误。 Facade(或代表)将负责组合数据。
然后Facade将有一个方法可以返回某种类型的集合,指示对象所代表的数据源,或哪些数据源失败 - 取决于客户端需要知道的内容。