Ale*_*onk 5 java design-patterns
我只是想找到Martin Fowler的Domain Model模式的一些例子而我不能.
从我在Internet上发现的域模型只是向类中添加一些"逻辑"方法.例如
public class Income {
private String title;
private String comment;
private String date;
private Double amount;
private Integer category;
public ExIn(String title, String comment, Double amount, Integer category, String date) {
this.title = title;
this.comment = comment;
this.date = date;
this.amount = amount;
this.category = category;
}
public Integer getCategory() {
return category;
}
public void setCategory(Integer category) {
this.category = category;
}
// more getters and setters
// Domain Model part starts
public boolean isPositive()
{
return amount > 0 ? true : false;
}
// more methods like that
}
Run Code Online (Sandbox Code Playgroud)
我理解正确吗?如果没有,我将非常感谢Domain Model Pattern的一个小例子.
dav*_*xxx 17
我理解正确吗?如果没有,我会感激一个小例子.
广义上,是的.
从马丁福勒,领域模型是既包含行为和数据域的一个对象模型.
域模型经常与您具有承载数据的特定类的模型以及承载行为/处理的一些其他特定类相对.
如果我接受你的Income类,它看起来更像是一个包含属性/数据的类而不是具有真实行为的域模型.
public boolean isPositive(){
return amount > 0 ? true : false;
}
Run Code Online (Sandbox Code Playgroud)
是一种与模型无关的效用函数.
你可以把它放在一个Math班级里.
我将尝试为您提供域模型示例,然后是模型分离数据和处理的版本.
假设在您正在建模的应用程序的域的要求中,我们需要为收入添加奖金.例如,这个奖金可以在圣诞节的冬天进行(但为什么不用于其他活动)
我们让域模型对象执行任务,而不是让服务类来执行此处理.
Incomes,高级对象可以迭代Income实例并应用奖金,我们可以有一个奖励规则类,根据一些输入值定义奖金.
我介绍了多个类,因为这个想法是允许每个对象根据他们的职责进行协作.
收入:
public class Incomes {
List<Income> incomes = ...
....
public void applyBonus(BonusRule bonusRule){
for (Income income : incomes){
income.applyBonus(bonusRule);
}
}
Run Code Online (Sandbox Code Playgroud)
收入:
public class Income {
private float amount;
...
public void applyBonus(BonusRule bonusRule){
float bonus = bonusRule.compute(this);
amount += bonus;
}
...
}
Run Code Online (Sandbox Code Playgroud)
ChristmasRule:
public class ChristmasBonusRule implements BonusRule {
...
@Override
public float compute(Income income){
float bonus = ...
return bonus;
}
...
}
Run Code Online (Sandbox Code Playgroud)
最后,我们可以通过这种方式应用处理:
void foo(){
// create a domain object that has both behavior and data
Incomes incomes = ...;
// invoke a functional method on the object by passing another domain object
incomes.applyBonus(new ChristmasBonusRule());
}
Run Code Online (Sandbox Code Playgroud)
在将不同类中的数据和逻辑分开的设计中,它看起来更像是:
public class IncomeBonusService {
// stateless : no incomes data inside it
....
public void applyChristmasBonus(List<Income> incomes){
for (Income income : incomes){
// Christmas bonus computation here
float bonus = ...
income.setAmount(bonus + income.getAmount());
}
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以用这种方式应用处理:
// inject the service
@Autowired
IncomeBonusService incomeBonusService;
void foo(){
// create a domain object that has only data
List<Income> incomes = ...;
// invoke a service method by passing data as parameter
incomeBonusService.applyChristmasBonus(incomes);
}
Run Code Online (Sandbox Code Playgroud)
对象没有行为的模型设计(只有getter/setter)称为Anemic Domain Model.
这个例子说明了两种方式之间的巨大差异:
领域模型:
对象很有意义.
在课堂之间精确定义的行为责任.
如此良好的隔离性,可测试性和可维护性.
例如,添加/删除/单元测试a BonusRule很容易.
负责其状态的对象.
实际上,不需要提供setter,因为对象本身可以在与其他对象协作后更新其状态.
我们可以在Amount.applyBonus():
float bonus = bonusRule.compute(this);
amount += bonus;
贫血领域模型:
所有逻辑都在服务类中.
所以一个地方来获取代码.
几行,很好.
但请注意,这种优势有一定的限制,因为随着逻辑变得庞大或复杂,最好的事情往往是在多个服务类中拆分逻辑.
但无论您需要多少Service类,整个逻辑都位于服务类中,而不是其他位置.如果我们将它与可能在类的某些不同"类型"中爆炸的逻辑域模型进行比较,这可能会简化开发规范.
为域类提供getter/setter的必要性.
域名不对其状态及其不变规则负责.
因此,任何依赖于域类的类都可以"破坏"其状态.
作为旁注,一些框架(用于持久性,映射,序列化......)默认依赖于getter/setter.
这就是为什么这个模型,尽管有它的缺点,在一些项目中引领.
你引用福勒的书是指拉尔曼的书,用于介绍性理解和例子.
有趣的是,Larman的域建模方法并没有向域类添加行为.
在域模型中有一个概念,即类是概念性的而不是软件类,但软件类基于域(概念)类.Larman实施行为的方法遵循责任驱动设计和GoF设计模式.
域模型仍然是软件开发过程中的一个独立元素.这种建模方式的好处在于您将问题与解决方案分开.域模型应该适用于问题(从问题域捕获需求而不解决实现细节).
Larman提出"操作合同"作为一种确保行为在域模型中保持一致的方法.同样,合同应该独立于解决方案(实现).合同具有后置条件,在操作发生后描述域模型中的约束.后置条件的示例是当顾客在商店中完成购买时,销售对象与顾客购买的每个商品相关联.
业务逻辑的实现应该遵守为域模型定义的合同(后置条件).Larman使用Controller GRASP模式以及其他GRASP模式的方法最终将此逻辑放在各种类(通常是域层,这是受域模型中的概念类启发的软件类)或处理系统的Façade(Controller)类中操作.
Larman的方法比这个解释更复杂,但重点是行为永远不会仅仅在域模型中定义为方法.Larman多次说域(概念)类没有方法,因为它们不是软件类.
福勒的书也提到了他在分析模式上写的另一本书的例子.
这些模式来自各个领域,包括医疗保健,金融交易和会计.每个模式都以文本方式和简单的UML前符号描述(本书是在UML稳定成可用形式之前编写的).
该书中的所有例子都没有显示软件类,即使用编程语言定义的方法(我能找到).
我至少知道一本书,其中分子生物学等领域的领域模型已经用UML出版.这是一个例子(注意UML被修改 - 子类型框显示在超类型框中 - 以节省空间):
上面的书没有对行为进行建模,可能是因为它们确实依赖于软件应用程序的要求.这些模型捕获了一些业务规则,例如:
- 每种化学品配方必须由2种或更多种化学元素或化学化合物或两者组成.
但该书中的模型主要是数据模型.
谷歌搜索将为您找到生物医学研究综合领域组(BRIDG)的这个巨大模型.Gene例如,向下钻取到分子生物学子域和类,您将看到它没有行为,也没有此域模型中的任何其他(概念)类.
Larman的哲学清楚地表明它们是独立于编程语言(概念而不是软件类),作为代码中的单独工件,将它们明确地绑定到问题域(需求).
另一方面,你会发现福勒说:"我更喜欢POJO域模型." ,这几乎是说域模型是在代码中定义的.
Eric Evans的DDD假设大多数软件开发中的一个重要复杂程度来自域,因此这种复杂域的模型对于管理复杂性至关重要.因此,当域很复杂时,域建模是必要的.DDD建议使用无处不在的域建模语言; 也就是说,域专家和开发人员都很常见.这意味着至少在某些情况下,域模型不会在编程语言中定义.
有一个相关的问题可能会产生一些亮点(尽管它产生了大量的热量).有些人批评这个问题的例子对于一个合理的领域模型来说太过琐碎(不够复杂).
| 归档时间: |
|
| 查看次数: |
8500 次 |
| 最近记录: |