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 ...
随机推荐
- VBoxGuestAdditions下载地址
http://dlc.sun.com.edgesuite.net/virtualbox/
- c# TCP/IP编程
这东西很多朋友都有写过了,我也就写着玩玩,就当做个笔记吧.不废话了. TCP/IP在数据通信中被广泛的使用,自然得包含客户端和服务端,当然,自己自言自语不是什么不可以,可那样貌似有点神经. 好了,那就 ...
- poj2388解题报告(排序)
POJ 2388,题目链接http://poj.org/problem?id=2388 题意: 水题一道 给定n个数,输出中间值,可以用sort,干脆快捷. 代码: //396K 32MS #incl ...
- android 编写动画
1.在编写动画的时候需要新建一个xml 新建的步骤是选中res单击右键选择Android resource file 然后弹出一个框 ,然后再Resource Type 里面选择Animation 然 ...
- python(5)- sys.stdout()实现进度条
1. 使用\r , 让其始终在行首输出,实现进度条 import sys, time ''' 使用\r 来实现进度条的效果,\r 是光标移到行首但不换行. 假设文件大小为60,一下下载1, 下载到60 ...
- 关于php一些数组函数
array_column($array,"key") 将二维数组中的键名为key的数据生成一个新数组 array_unique($array) 去除重复值
- Java操作图片的工具类
操作图片的工具类: import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.a ...
- BZOJ1975 [Sdoi2010]魔法猪学院
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- CSS之照片翻转
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...
- 省市数据递归加载到TreeView
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...