基础知识漫谈(5):应用面向对象来分析“语言”
万物皆对象。
如果面试官问你“什么是面向对象”,万物皆对象就是个很好的开场白。
在网上认识的一些新人(甚至部分有三五年经验的老鸟),在谈论到面向对象\面向过程的时候,就陷入了误区。
误区一,面向对象和面向过程是非此即彼的对立方,相互不兼容。
误区二,面向对象是种形而上的东西,“实际”开发中压根没用。
会产生这些误区,本质上,都是不理解面向对象和面向过程是什么,陷入了教条主义,所以这里统一一起说明。面向对象(OOP)是为了方便开发而产生的,它把常识中的概念,抽象成了对应的类。举一个例子,猫吃老鼠
|
猫 |
吃 |
老鼠 |
语法层面 |
名词·主语 |
动词·谓语 |
名次·宾语 |
面向对象层面 |
猫类 |
猫类的方法 |
老鼠类 |
程序表达层面 |
cat |
.eat |
(mouse) |
我们可以看到,日常语法结构,和程序语言结构达到了统一。反过来推论这个例子:Animal animal=new Cat();
在日常语言里怎么表达呢?这个动物,是一只猫。
这一句话,就应用到了OOP三个基本特性里的多态和继承。在常识里,动物的概念是囊括了猫的概念的,那么,我们说“那里有一只动物”,语法上毫无问题,但是那只“动物”就仅仅只是动物了么?“动物”作为一种抽象概念,它在实际中并不能独立存在是不是?它必须得是一只猫,或者一只老鼠。但它绝不能是一个瓶子。
综上,我们可以推论得出:
1、动物是个抽象概念,所以Animal应当是个抽象类或者接口,你绝不能写出new Animal();这样的语句出来。
2、老鼠和猫是继承\实现自Animal的,而瓶子不是。
3、谈论到类的时候,要分清语境,到底是谈论的类定义还是类实例,比如猫这个概念,是类定义,具体的某一只猫就是类的实例。也就是Cat和某个cat=new Cat()的区别。
说完了这些,我们来应用这些基础知识实际的分析SQL语句本身,来看看面向对象到底有没有实际作用。
select * from user where id>1 and name<>’Abby’ group by sexsual sort by age
分析开始:
1、这是一条SQL语句,所以,我们需要有一个类SQLStatement
2、具体而言,这是一条Select语句,所以,会有class SelectStatement extends SQLStatement
3、该类语句的基本结构是select [Columns] from [Table] [Where][GroupBy][SortBy]
select和from是特定关键字,用字符串记录在SelectStatement即可,Columns、Table、Where、GroupBy、SortBy都是SQL元素(SQLElement),明显的,和SQL语句有相似性又有所不同。这里提出一个更加抽象的概念SQL模型(SQLModel)。使SQLStatement\SQLElement implements SQLModel。
ColumnElement,TableElement,WhereElement等等类的设计是不是也理所当然了?
下面特别讲解下ColumnElement和WhereElement的设计问题。
在SQLStatement中能存在多个ColumnElement,所以需要一个集合结构来存放ColumnElement。
一个Column,应当具备列名和别名。所以ColumnElement会具备String类型的name属性和alias属性。
结构如图所示:
WhereElement就要复杂一些,本质上来说,Where表达的是查询条件,查询条件又是由一个到多个条件表达式(Expression)组成,
简单的表达式(SimpleExpression)如:
a、id=1
b、id between 0 and 10
c、name like ‘N%’
可以总结出,SimpleExpression结构大致如下:[列名\别名] [操作符] [值]
复合的表达式(ComplexExpression),则是在简单的基础上加上AND\OR条件,如:
id=1 AND id between 0 and 10
也就是说,ComplextExpression结构如下:[左侧表达式][条件][右侧表达式]
思考一个问题,A AND B OR C这样的结构,要如何使用符合表达式来展现呢?
解答,我们可以把 A AND B OR C视为 Exp1 = A AND B,Exp2= Exp1 OR C。综上,我们可以大概得出WhereElement的设计如下:
应用以上的思路,我们可以想想,子查询要怎么映射成我们的SQLModel呢?这里不再详细解答,可以注意,在SimpleExpression里,[值]部分我使用了一个ValueModel,对于它的设计将会带给你答案。
完成这些设计后,究竟要怎么使用它呢?
对于熟悉面向对象的读者来着,这道理是显而易见的,我这里举一个例子:输出SQL语句。
试想,JavaBean是可以灵活组合的,现在,你已经组合出了一个你满意的SelectStatement,要如何拼装出对应的SQL呢?答案是,调用toSQL()方法。SelectStatement#toSQL()大概输出如下:
Select [遍历ColumnElement#toSQL()] From [TableElement#toSQL()] [WhereElement#toSQL()] [GroupByElement#toSQL()][SortByElement#toSQL()]
ColumnElement#toSQL()会输出为ID nid这样的格式。
WhereElement#toSQL()则遍历它内部的Expression#toSQL()向下迭代输出。
每一个语句块的输出格式由它自身负责,语句块之间的组织由上一级的语句块负责,最终,就达到了灵活拼装SQL的效果。
思考一个问题:我们有没有思路,将SQL语句分析成模型呢?
下篇文章会谈谈我在招聘时遇到的一些情况,希望会对正在找工作的朋友有所帮助。