1.编程基本原则(SOLID)
1.1Single Responsibility Principle:单一职责原则
1.2 Open Closed Principle:开闭原则
定义:在不修改源码的情况下改变其行为。
本质思想:
以抽象来固定不变的东西
使用具体实现对可变性进行封装(封装=隐藏)
面向抽象编程
1.3 Liskov Substitution Principle:里氏替换原则
目的:为继承提供的规范,使功能的容错率更高。如果不满足也可能保证程序正常运行,但是进行多态调用会产生意想不到的问题。
含义:
1)子类必须完全实现父类的抽象方法,但不能重写父类的非抽象方法
2)子类重写父类的抽象方法时,子类方法的入参要比父类方法的输入参数更宽松
3)子类方法实现父类的抽象方法时,方法的返回类型要比父类更严格
4)子类可以增加自己特有的方法
1.4 Law of Demeter:迪米特法则
不要和陌生人说话。减少类与类之间的依赖。
1.5 Interface Segregation Principle:接口隔离原则
不要使用总接口的方式,尽量减少对子类的影响。
1.6 Dependence Inversion Principle:依赖倒置原则
核心是面向抽象(抽象类/接口)编程,完成多态。
想要避免面条式的代码,那么上面六种规则必须熟记于心。
2.接口与抽象类
这个老生常谈了,在学习语法的初级阶段,肯定都接触过,但是一般只停留在语法阶段,abstract类可以有abstract方法,子类继承抽象类必须实现抽象方法。但是脱离语法站在更高维度,也就是在设计功能的时候这两者究竟有什么区别?什么类应该是抽象类?哪些功能应该放在接口中?
个人理解,抽象类是对事物本身的抽象,即
对一类事物根本属性和行为的抽象,方法则是对事物局部行为的抽象。比如门都有门把手,门框,支持开/关功能,这些应该放在Door抽象类中,但是现在有的门支持监控功能,这个功能肯定是局部的,就应该放在接口中。
abstract class Door {
public abstract void open();
public abstract void close();
}
interface Watch{
void watch();
}
class WatchDoor extends Door implements Watch {
void oepn() {
//....
}
void close() {
//....
}
void watch() {
//....
}
}
3.变与不变
在设计功能前,需要深入理解功能的变与不变,不变的点一般来说就是功能的流程节点,如数据库查询需要建立连接,拼装参数,发送请求,接收返回参数。变化的点就是不同的数据库厂商对这几个步骤的规范不同,所以我们将不变进行抽象,变化的部分交由子类实现,然后由调用方选取不同的子类完成功能。
4.设计过程中如何预测变化
不要假想需求,一般是功能第二次扩展真实出现再考虑引入设计模式。一般提前预设的变化总是和真实的变化背道而驰,前期引进的设计理念往往不符合实际最后还是推到重来。