封装:作用是信息保护,类通过暴露有限的接口,让外部通过函数来访问内部数据。
抽象:隐藏方法的具体实现,调用者只需关心方法提供了哪些功能,忽略如何实现。
继承:表示类之间is-a的关系,便于代码复用。
多态:子类可以替换父类/接口。提高代码的可扩展性、可复用性。
滥用getter、setter方法:违背了封装性,给用户带来过度的自由,可能会导致数据不一致。比如get到一个属性List infos,那用户就可以随意操作infos的元素了,此时并没有更新该类中和infos数据关联的其他属性。
滥用全局变量和全局方法:
问题一:
大而全的Consotant类(存全局常量)要避免,容易造成冲突影响代码可维护性,增加代码编译时间,也会让其他模块引入大量的无效常量影响复用性。
解决方案:分为多个类,AConstants,BConstants。
问题二:
Utils类 ,大的Utils类(存全局方法)也有上面的问题。
抽象类是is-a的关系,为了解决代码复用问题。
接口是has-a的关系,表示具有某一组行为特征,解耦。 接口的本质是一组约定,是功能提供者给使用者的一个功能列表。
举个接+组合+委托的例子:
public interface Runable{
void run();
}
public class RunAbility implements Runable{
void run(){
//具体实现
}
}
public class Chicken implements Runable,Flyable{ //接口
private RunAbility runAbility= new RunAbility(); //组合
private FlyAbility flyAbility = new Flyability(); //组合
public void run(){
runAbility.run(); //委托
}
public void fly(){
flyability.fly();
}
}
继承有三种作用,表示类之间的is-a关系、解决代码复用的问题、支持多态的特性。这三个作用可以通过组合、接口、委托来达成。为了避免但继承层次过深,过复杂影响代码的课维护性,我们应该少用继承。
贫血模型中,VO、BO、Entity都属于纯粹的数据结构,业务逻辑主要在Service层中,这种模型将操作和数据分离,破坏了面向对象的封装特性,是一种典型的面向过程的风格。但对于业务不复杂的系统来说,这种模型简单而且够用。
充血模型要数据和对应的业务逻辑封装到同一个类中,属于面向对象的风格。DDD(Domain Driven Design)领域驱动设计。和贫血模型相比,该模型把业务逻辑放到Domain中,Service变得很薄,此时Service层负责的事情是:和Repository打交道、调用多个领域模型、和其他系统交互(记日志、发消息、事务、RPC等)
基于充血模型的DDD和贫血模型相比,Controller层和Repository层基本一样,差异主要是在Service层。