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 ...
随机推荐
- python学习笔记(三)--条件语句
Python 条件语句 Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. Python 编程中 if 语句用于控制程序的执行,基本形式为: if 判断条 ...
- Android(java)学习笔记81:java异常处理机制
1.try....catch/try...catch...finally package cn.itcast_02; /* * 我们自己如何处理异常呢? * A:try...catch...final ...
- ArcGIS动态文本
处理动态文本 来自:http://resources.arcgis.com/zh-cn/help/main/10.2/index.html#/na/00s900000013000000/ Deskto ...
- spring-boot配置外部静态资源的方法
import java.io.File; import javax.servlet.Servlet; import lombok.extern.slf4j.Slf4j; import org.spri ...
- Oracle 追踪回话SQL几种方法
生成sql trace可以有以下几种方式: 1.参数设置:非常传统的方法. 系统级别: 参数文件中指定: sql_trace=true 或 SQL> alter system set sql_t ...
- 怎么删除远程登录连接的ip
通过远程桌面可以登录到远程电脑上进行相应的操作,在登录过后会在本地电脑上留下登录过的IP以及登录用户名相关信息,可能会给远程的电脑带来安全隐患,下面介绍一下清除远程桌面历史记录的方法. 1.删除我的文 ...
- 【dp入门题】【跟着14练dp吧...囧】
A HDU_2048 数塔 dp入门题——数塔问题:求路径的最大和: 状态方程: dp[i][j] = max(dp[i+1][j], dp[i+1][j+1])+a[i][j];dp[n][j] = ...
- Leetcode 190. Reverse Bits(反转比特数)
Reverse bits of a given 32 bits unsigned integer. For example, given input 43261596 (represented in ...
- PhotoShop—剪贴蒙版
工作中发现剪贴蒙版方便好用,所以简单分享下~ 一.剪贴蒙版有什么作用 1.文字上色 2.裁剪图片 3.添加背景 等 二.剪贴蒙版怎么使用 1.新建层,打上字如图 2.文字上面再建层加上效果如渐变 3. ...
- Tomcat - 持久化 Session
Session 是保存在内存中的,如果服务器重启.宕机的话,Session 就会丢失.有时候,我们需要对 Session 持久化以应对意外的情况发生.例如,客户端与服务器在交互过程中,可能因为 Ses ...