您好,登錄后才能下訂單哦!
隨著軟件開發(fā)技術(shù)不停地迭代更新,現(xiàn)在的系統(tǒng)基本上實(shí)現(xiàn)了由表示、邏輯一體化到分層模式的轉(zhuǎn)變。
一個(gè)好的層次劃分不僅僅可以使代碼結(jié)構(gòu)更加清晰、增添代碼可讀性。同時(shí)也使得項(xiàng)目分工更加明確,維護(hù)更為便利。
而我要介紹的是在java開發(fā)領(lǐng)域中,面向?qū)ο蟮姆謱幽J?領(lǐng)域模型分層。
領(lǐng)域模型分層最主要的工作就是分離領(lǐng)域,分離領(lǐng)域就是將領(lǐng)域?qū)ο笈c系統(tǒng)中的其他功能分離,從而避免將領(lǐng)域概念和其他只與軟件技術(shù)相關(guān)的的概念相混淆,其最終目的是為了讓對象更專注于邏輯處理而無需關(guān)注其他的事物。
領(lǐng)域模型設(shè)計(jì)書籍曾描述過領(lǐng)域模型可分為4層,分別是
1、用戶界面層
負(fù)責(zé)向用戶顯示信息和解釋用戶指令
2、應(yīng)用層
定義軟件要完成的任務(wù),并指揮表達(dá)領(lǐng)域概念的對象來解決問題
3、領(lǐng)域?qū)樱P蛯樱?br/>負(fù)責(zé)表達(dá)業(yè)務(wù)概念,業(yè)務(wù)狀態(tài)信息以及業(yè)務(wù)規(guī)則
4、基礎(chǔ)設(shè)施層
為各層提供通用的技術(shù)能力,為應(yīng)用層傳遞消息,為領(lǐng)域?qū)犹峁┏志没瘷C(jī)制。
在結(jié)合實(shí)際的開發(fā)經(jīng)驗(yàn)與書本的知識(shí),認(rèn)為在開發(fā)過程中可落地成如下幾層:
Controller層【用戶界面層】、Service層【應(yīng)用層】、Action層【應(yīng)用層】、entity層【領(lǐng)域?qū)印?、DAO層【基礎(chǔ)設(shè)施層】。
其層與層的關(guān)系如下圖:
為了更好的理解上述分層架構(gòu),舉個(gè)栗子來說明一下。
先設(shè)定一個(gè)場景:
有一家服裝店,店里有店長和多個(gè)導(dǎo)購。該店有一批會(huì)員,為了更好的服務(wù)會(huì)員,店長需要將會(huì)員分配給導(dǎo)購,讓導(dǎo)購服務(wù)自身的會(huì)員。
待實(shí)現(xiàn)功能:給導(dǎo)購分配會(huì)員
作用:
1、負(fù)責(zé)接待外來用戶,并將請求傳遞給下一層
2、校驗(yàn)請求的合法性【如:判斷用戶合法性,請求參數(shù)合理性】
3、相應(yīng)用戶請求【系統(tǒng)將請求處理完畢后,將返回的結(jié)果組合成用戶想要的結(jié)果】
代碼:
package com.csosm.layout.controller;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.collections.MapUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.csosm.layout.service.EmployeeService;
import com.google.common.base.Splitter;
/**
* 用戶界面層,為前端或其他系統(tǒng)用戶提供訪問接口
* @author bear
*
*/
@RequestMapping("/employee")
public class EmployeeController {
/**
* 對外提供添加為導(dǎo)購添加會(huì)員接口
* @param requestMap 請求數(shù)據(jù)(memberIds:【注:會(huì)員ID集合,會(huì)員ID間以逗號(hào)隔開】,employeeId:【注:導(dǎo)購ID】)
* @param request
* @return 視圖
*/
@RequestMapping(value = "/members/add.json")
@ResponseBody
public Map<String,Object> addMembers(@RequestBody Map<String, String> requestMap,
HttpServletRequest request){
//進(jìn)行請求參數(shù)校驗(yàn)
if(!requestMap.containsKey("memberIds")&&!requestMap.containsKey("employeeId"))
throw new IllegalArgumentException("請求參數(shù)缺少[memberIds]或[employeeId]");
//從請求參數(shù)中提取會(huì)員ID集合
List<Integer> memberIds = Splitter.on(",").splitToList(MapUtils.getString(requestMap, "memberIds"))
.stream().map(x -> Integer.parseInt(x)).collect(Collectors.toList());
//從請求參數(shù)中提取導(dǎo)購ID
Integer employeeId = MapUtils.getInteger(requestMap, "employeeId");
employeeService.addMembers(employeeId, memberIds);
return null;//自行定義返回成功
}
@Resource
private EmployeeService employeeService;
}`
Service層【應(yīng)用層】:對接Controller層,為Controller層的每一個(gè)請求提供對應(yīng)的接口,為下一層Action層做數(shù)據(jù)準(zhǔn)
作用:
1、將controller傳遞的數(shù)據(jù)還原成對象
2、進(jìn)行跨對象邏輯處理
代碼:
package com.csosm.layout.service;
import java.util.Collection;
import java.util.Objects;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import com.csosm.layout.action.EmployeeAction;
import com.csosm.layout.action.MemberAction;
import com.csosm.layout.entity.Employee;
import com.csosm.layout.entity.Member;
/**
* Employee的應(yīng)用層,可跨對象操作
* @author bear
*
*/
public class EmployeeService {
/**
* 為導(dǎo)購添加多個(gè)會(huì)員
* @param employeeId 導(dǎo)購ID
* @param memberIds 會(huì)員ID
*/
public void addMembers(Integer employeeId,Collection<Integer> memberIds) {
Objects.requireNonNull(employeeId,"導(dǎo)購ID[employeeId]不能為空");
if(CollectionUtils.isEmpty(memberIds)) return ;//如果傳入的會(huì)員ID為空,則返回
Employee employee = employeeAction.getById(employeeId);
Collection<Member> members = memberAction.getByIds(memberIds);
if(CollectionUtils.isEmpty(members)) return ;//如果根據(jù)會(huì)員ID獲取的會(huì)員數(shù)目為空,則返回
employeeAction.addMembers(employee, members);
}
@Resource
private EmployeeAction employeeAction;
@Resource
private MemberAction memberAction;
}
* Action層【應(yīng)用層】:該層只對Entity層負(fù)責(zé),是Entity層對外提供的接口
作用:
1、為系統(tǒng)內(nèi)部提供操作實(shí)體的接口
2、調(diào)用dao層持久化對象
代碼:
package com.csosm.layout.action;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import javax.annotation.Resource;
importorg.apache.commons.collections.CollectionUtils;
import com.csosm.layout.dao.EmployeeDAO;
import com.csosm.layout.entity.Employee;
import com.csosm.layout.entity.Member;
/**
* 獨(dú)屬于Employee對象的應(yīng)用層
* 盡量使用對象
* @author bear
*
*/
public class EmployeeAction {
/**
* 給導(dǎo)購添加多個(gè)會(huì)員
* @param employee 導(dǎo)購
* @param members 多個(gè)會(huì)員
*/
public void addMembers(Employee employee,Collection<Member> members) {
Objects.requireNonNull(employee,"導(dǎo)購[employee]不能為空");//校驗(yàn)導(dǎo)購
if(CollectionUtils.isEmpty(members)) return ;//校驗(yàn)會(huì)員
employee.addMembers(members);//業(yè)務(wù)邏輯處理,為導(dǎo)購添加會(huì)員
empDao.updateEmployee(employee);//持久化到數(shù)據(jù)庫
}
/**
* 根據(jù)導(dǎo)購ID獲取導(dǎo)購對象
* @param employeeId
* @return
*/
public Employee getById(Integer employeeId) {
Objects.requireNonNull(employeeId,"導(dǎo)購ID[employeeId]不能為空");
Employee employee = empDao.selectById(employeeId);
if(null == employee)
throw new IllegalStateException(String.format("不存在導(dǎo)購[%s]", employeeId));
return employee;
}
@Resource
private EmployeeDAO empDao;
}
package com.csosm.layout.action;
import java.util.Collection;
import java.util.Collections;
import javax.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import com.csosm.layout.dao.MemberDAO;
import com.csosm.layout.entity.Member;
/**
* 獨(dú)屬于Member對象的應(yīng)用層
* @author bear
*
*/
public class MemberAction {
/**
* 根據(jù)會(huì)員ID獲取會(huì)員對象
* @param memberIds
* @return
*/
public Collection<Member> getByIds(Collection<Integer> memberIds){
if(CollectionUtils.isEmpty(memberIds)) return Collections.EMPTY_LIST;//如果會(huì)員ID為空則返回空列表
return memberDao.selectByIds(memberIds);
}
@Resource
private MemberDAO memberDao;
}
* Entity層【領(lǐng)域?qū)印浚核械臉I(yè)務(wù)操作集中在Entity層。
作用:
1、進(jìn)行業(yè)務(wù)邏輯的處理
代碼:
package com.csosm.layout.entity;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.commons.collections.CollectionUtils;
import com.google.common.collect.Lists;
public class Employee {
//導(dǎo)購ID
private final Integer id;
//導(dǎo)購名稱
private String name;
//導(dǎo)購門店
private Integer storeId;
//導(dǎo)購手上的會(huì)員 ,初始化為空
private List<Integer> memberIds = Lists.newArrayList();
public Employee(Integer id, String name, Integer storeId) {
super();
this.id = id;
this.name = name;
this.storeId = storeId;
}
/**
* 添加單個(gè)會(huì)員
* @param member
*/
public void addMember(Member member) {
Objects.requireNonNull(member,"入?yún)ember不能為空");//檢驗(yàn)會(huì)員
this.memberIds.add(member.getId());
}
/**
* 為導(dǎo)購添加多個(gè)會(huì)員
* @param members
*/
public void addMembers(Collection<Member> members) {
if(CollectionUtils.isEmpty(members)) return ;//如果沒有傳入會(huì)員則返回
this.memberIds.addAll(members.stream().map(x -> x.getId()).collect(Collectors.toSet()));
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getStoreId() {
return storeId;
}
public void setStoreId(Integer storeId) {
this.storeId = storeId;
}
public List<Integer> getMemberIds() {
return memberIds;
}
public Integer getId() {
return id;
}
//toString、equals、hasCode 方法就不寫了
}
package com.csosm.layout.entity;
public class Member {
//會(huì)員ID
private final Integer id;
//會(huì)員 名稱
private String name;
//會(huì)員電話
private String phone;
//會(huì)員性別
private int sex;
public Member(Integer id, String name, String phone, int sex) {
super();
this.id = id;
this.name = name;
this.phone = phone;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public Integer getId() {
return id;
}
}
* dao層【基礎(chǔ)設(shè)施層】:實(shí)現(xiàn)將對象持久化到數(shù)據(jù)庫
代碼:
package com.csosm.layout.dao;
import com.csosm.layout.entity.Employee;
/**
* 獨(dú)屬于Employee的持久化層
* @author bear
*
*/
//以下操作可采取MYbatis的方式,也可以采取spring自帶的jdbcTemplate的方式就行對象持久化并與數(shù)據(jù)進(jìn)行交互
public class EmployeeDAO {
/**
* 更新導(dǎo)購對象到數(shù)據(jù)庫
* @param employee 導(dǎo)購
*/
public void updateEmployee(Employee employee) {
//TODO 實(shí)現(xiàn)對象持久化
}
/**
* 根據(jù)導(dǎo)購ID從數(shù)據(jù)庫中提取導(dǎo)購對象
* @param id 導(dǎo)購ID
* @return
*/
public Employee selectById(Integer id) {
//TODO 從數(shù)據(jù)庫中獲取導(dǎo)購對象
return null;
}
}
package com.csosm.layout.dao;
import java.util.Collection;
import com.csosm.layout.entity.Member;
/**
* 獨(dú)屬于Member的持久化層
* @author bear
*
*/
//以下操作可采取MYbatis的方式,也可以采取spring自帶的jdbcTemplate的方式就行對象持久化并與數(shù)據(jù)進(jìn)行交互
public class MemberDAO {
/**
* 根據(jù)多個(gè)會(huì)員ID從數(shù)據(jù)庫獲取多個(gè)會(huì)員
* @param memberIds 會(huì)員ID集合
* @return
*/
public Collection<Member> selectByIds(Collection<Integer> memberIds){
//TODO 從數(shù)據(jù)庫提取會(huì)員信息
return null;
}
}
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。