Spark小课堂Week7 从Spark中一个例子看面向对象设计
Spark小课堂Week7
从Spark中一个例子看面向对象设计
今天我们讨论了个问题,来设计一个Spark中的常用功能。
功能描述:数据源是一切处理的源头,这次要实现下加载数据源的方法load()
初始需求
需求:支持Json数据源加载
具体:输入一个path,需要返回一个Relation,
Relation中提供scan()和write()两个方法
示意代码:
class Context{
public Relation json(String path){
return new Relation(path);
}
}
class Relation{
public Relation(path);
public scan();
public write();
}
第一次需求变化
现在需要添加jdbc数据源,输入的是url和tableName,需要有自己的Relation实现
简单实现:
class Context{
public JsonRelation json(String path){
return new JsonRelation(path);
}
public JdbcRelation jdbc(String url,String tableName){
return new JdbcRelation(url,tableName);
}
}
class JsonRelation{
public JsonRelation(String path);
public scan();
public write();
}
class JdbcRelation{
public JdbcRelation(String url,String tableName);
public scan();
public write();
}
这个实现明显违反了开放封闭原则,增加一种文件格式,需要对核心类Context进行修改!!!
方法整合
所以首先,需要对json和jdbc方法进行合并为format,参数也进行合并,
source参数表示数据源,是一个字符串,比如:"json"、"jdbc"
逻辑整合起来
class Context{
public Relation format(String source,Map param){
if(source == "json") return new JsonRelation(param.get("path"));
if(source == "jdbc") return new JdbcRelation(param.get("url"),param.get("tableName"));
...
}
}
class JsonRelation extends Relation{
public JsonRelation(String path);
public scan();
public write();
}
class JdbcRelation extends Relation{
public JdbcRelation(String url,String tableName);
public scan();
public write();
}
方法通用化。
format方法还是违反了开放封闭原则。我们可以使用反射对其进行通用化。
class Context{
public Relation format(String source,Map param){
Class c = Class.forName(source + "Relation");
Constructor constructor= c.getDeclaredConstructor(Map.class);
return constructor.newInstance(param);
...
}
}
class JsonRelation extends Relation{
public JsonRelation(Map param){
this.path = param.get("path");
};
public scan();
public write();
}
class JdbcRelation extends Relation{
public JdbcRelation(Map param){
this.url = param.get("url");
this.tableName = param.get("tableName");
}
public scan();
public write();
}
第二次需求变化
需求:再增加一种文件类型csv,同样是输入path
按照之前的思路,我们可以增加一个Relation类
class CsvRelation extends Relation{
public CsvRelation(Map param){
this.path = param.get("path");
};
public scan();
public write();
}
这里有一个问题,我们其发现构造方法和JsonRelation是完全重复的,有没有办法消除这种重复
消除重复,第一点是需要把重复的部分拆离出来。我们把Relation类拆分为Relation类和Provider类。其中Provider是一个工厂方法,通过反射来调用。
class Context{
public Relation format(String source,Map param){
Class c = Class.forName(source + "Provider");
Method method= c.getMethod("getRelation",Map.class);
return method.invoke(null,param);
...
}
}
class JsonProvider{
public static createRelation(Param param){
return new JSonRelation(param.get("path"));
};
}
class JsonRelation extends Relation{
public JsonRelation(String path);
public scan();
public write();
}
class CsvProvider{
public static createRelation(Param param){
return new CsvRelation(param.get("path"));
};
}
class CsvRelation extends Relation{
public CsvRelation(String path);
public scan();
public write();
}
class JdbcProvider{
public static Relation createRelation(Param param){
return new JdbcRelation(param.get("url"),param.get("tableName"));
};
}
class JdbcRelation extends Relation{
public JdbcRelation(String path,String tableName);
public scan();
public write();
}
Json和csv采用path构造,而jdbc使用url+table,这个可以认为是一个固有的规则,我们可以把构造中间重复的逻辑再单独抽取出来
class Context{
public Relation format(String source,Map param){
Class c = Class.forName(source + "Provider");
if(hasIntereface(c,PathProvider.class)){
Method method= c.getMethod("getRelation",String.class);
return method.invoke(null,param.get("path"));
}
if(hasIntereface(c,UrlProvider.class)){
Method method= c.getMethod("getRelation",String.class,String.class);
return method.invoke(null,param.get("url"),param.get("tableName"));
}
...
}
}
class JsonProvider implements PathProvider{
public static createRelation(String path){
return new JSonRelation(path);
};
}
class CsvProvider implements PathProvider{
public static createRelation(String path){
return new CsvRelation(path);
};
}
class JdbcProvider implements UrlProvider{
public static Relation createRelation(String url,String tableName){
return new JdbcRelation(url,tableName);
};
}
然后,我们发现format方法中的实现有些太复杂,所以单独抽取出来
class Context{
public Relation format(String source,Map param){
return Provider.getRelation(source,param);
}
}
class Provider{
public Relation getRelation(String source,Param,param){
Class c = Class.forName(source + "Provider");
if(hasIntereface(c,PathProvider.class)){
Method method= c.getMethod("getRelation",String.class);
return method.invoke(null,param.get("path"));
}
if(hasIntereface(c,UrlProvider.class)){
Method method= c.getMethod("getRelation",String.class,String.class);
return method.invoke(null,param.get("url"),param.get("tableName"));
}
...
}
}
小结
未完待续。
这个例子主要是进行对象的构造,是比较有通用性的。
我们可以看到,面向对象设计中,主要是靠不同对象的特性来实现变化。
而对于对象的构造会需要一些规则来驱动,这种规则我们一般抽象为接口来标识,
处理这些规则的往往都是工厂方法,也是工厂的一个非常重要的作用。
Spark小课堂Week7 从Spark中一个例子看面向对象设计的更多相关文章
- Spark小课堂Week1 Hello Spark
Spark小课堂Week1 Hello Spark 看到Spark这个词,你的第一印象是什么? 这是一朵"火花",官方的定义是Spark是一个高速的.通用的.分布式计算系统!!! ...
- Spark小课堂Week6 启动日志详解
Spark小课堂Week6 启动日志详解 作为分布式系统,Spark程序是非常难以使用传统方法来进行调试的,所以我们主要的武器是日志,今天会对启动日志进行一下详解. 日志详解 今天主要遍历下Strea ...
- Spark小课堂Week5 Scala初探
Spark小课堂Week5 Scala初探 Scala是java威力加强版. 对Java的改进 这里会结合StreamingContext.scala这个代码说明下对Java的改进方面. 方便测试方式 ...
- Spark小课堂Week4 从控制台看Spark逻辑结构
Spark小课堂Week4 从控制台看Spark逻辑结构 层级关系: 从监控控制台,我们可以看到如下关系: 一个 Job 包含 n Stage 一个 Stage 包含 n Task Job0解决什么问 ...
- Spark小课堂Week3 FirstSparkApp(Dataframe开发)
Spark小课堂Week3 FirstSparkApp(代码优化) RDD代码简化 对于昨天练习的代码,我们可以从几个方面来简化: 使用fluent风格写法,可以减少对于中间变量的定义. 使用lamb ...
- Spark小课堂Week3 FirstSparkApp(RDD开发)
Spark小课堂Week3 FirstSparkApp 问题:Java有哪些数据结构 大致有如下几种,其中List与Map是最重要的: List Map Set Array Heap Stack Qu ...
- Spark小课堂Week2 Hello Streaming
Spark小课堂Week2 Hello Streaming 我们是怎么进行数据处理的? 批量方式处理 目前最常采用的是批量方式处理,指非工作时间运行,定时或者事件触发.这种方式的好处是逻辑简单,不影响 ...
- (转载)小课堂UI-有关配色的一个小技巧
- PJzhang:安全小课堂-安全软件为什么很重要,看这里!
猫宁!!! 参考链接: http://www.360.cn/webzhuanti/mianyigongju.html https://www.freebuf.com/fevents/204100.ht ...
随机推荐
- BootStrap2学习日记2--将固定布局换成响应式布局
概要:响应式页面是指页面根据浏览平台(尺寸)的不同显示不同的CSS. 原理:在Html的的头加入代码 <style> /*当浏览器宽度大于767是 采用括号里面的CSS样式*/ @medi ...
- Eclipse插件的安装方法
转自:http://blog.csdn.net/zhangyabinsky/article/details/7043435 Eclipse插件的安装有两种方法 :一个是在线安装,另一个就是手动安装. ...
- hadoop学习记录(二)HDFS java api
FSDateinputStream 对象 FileSystem对象中的open()方法返回的是FSDateInputStream对象,改类继承了java.io.DateInoutStream接口.支持 ...
- Content-Type一览
文件扩展名 Content-Type(Mime-Type) 文件扩展名 Content-Type(Mime-Type) .*( 二进制流,不知道下载文件类型) application/octet-st ...
- [未完成]关于Maven的使用总结
什么是maven 翻译为“专家”,“内行” Maven是跨平台的项目管理工具.主要服务于基于Java平台的项目构建,依赖管理和项目信息管理. 什么是理想的项目构建? 高度自动化,跨平台,可重用的组件, ...
- 实现TableLayout布局下循环取出TableRow控件中的文字内容到list集合
布局方式为TableLayout,利于实现表单样式展现. <!-- 详情内容区域 --> <ScrollView android:layout_above="@id/id_ ...
- MySQL同主机不同数据库的复制命令
MySQL同主机不同数据库的复制命令:注意运行在Terminal中,不运行在MySQL命令行中. 1 mysqldump Portal_DEV -u root -ppassword1$ --add-d ...
- Sqlite官方下载对应版本注意细节
官网下载地址: http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki 下载注意事项: 1.对应.net平台 2.对 ...
- Servlet & JSP - Java Web 访问资源的路径问题
假设 Web 工程的目录结构如下图所示,并且 HelloServlet 配置为 @WebServlet(name = "helloServlet", urlPatterns = { ...
- Android之帧动画
MySurfaceView类: package com.fm; import android.content.Context; import android.graphics.Bitmap; impo ...