Builder模式实战1
一.目的
通过实际的项目代码来熟悉并且深入理解Builder的作用,并了解该模式的优缺点.
二.作用
Builder模式的作用
1.简化代码结构
当一个类中属性比较多时,而构建对象时,也并非每一个属性都要用。如果此时用构造函数来够造对象.时,需要重载多次构造方法。或者使用一个方法需要重载多次。
重载方法多了会造成类非常臃肿,且不好维护,此时可以把这些属性抽离出去,或者把创建对象委托给另外一个类。
2.封装和解耦
将创建对象的方法隐藏起来,外部调用者只管传参,不用管创建者内部如何创建该对象。
3.控制权反转,方便配置
将对象的创建权交给Builder类,可将对象的属性传递和被创建对象隔离开,方便使用配置文件来配置创建对象
4.可复用对象,避免重复的new对象造成内存开销,并且很容易的结合缓存和对象池来使用
三.未重构前的代码
重载方法多,传入属性多,且有些是可选的
public static boolean createTable(String tableName, String cf, boolean inMemory, int ttl, int maxVersion){
HTableDescriptor htd = createHTableDescriptor(tableName, cf, inMemory, ttl, maxVersion, COPROCESSORCLASSNAME);
return createTable(htd);
}
public static boolean createTable(String tableName, String cf, boolean inMemory, int ttl, int maxVersion, boolean useSNAPPY){
HTableDescriptor htd = createHTableDescriptor(tableName, cf, inMemory, ttl, maxVersion, useSNAPPY , COPROCESSORCLASSNAME);
return createTable(htd);
}
public static boolean createTable(String tableName, String cf, boolean inMemory, int ttl, int maxVersion, boolean useSNAPPY, byte[][] splits){
HTableDescriptor htd = createHTableDescriptor(tableName, cf, inMemory, ttl, maxVersion, useSNAPPY, COPROCESSORCLASSNAME);
return createTable(htd , splits);
}
public static boolean createTable(String tableName,
String cf,
boolean inMemory,
int ttl,
int maxVersion,
byte[][] splits){
//创建表描述类 设置表的结构和参数
HTableDescriptor htd = createHTableDescriptor(tableName, cf, inMemory, ttl, maxVersion, COPROCESSORCLASSNAME);
//通过HTableDescriptor 和 splits 分区策略来定义表
return createTable(htd , splits);
}
四.角色划分

五.具体代码
HBaseTableOperatorBase.java
public class HBaseTableOperatorBase {
protected HBaseConf conf = HBaseConf.getInstance();
protected final Logger LOG = LoggerFactory.getLogger(HBaseTableOperatorBase.class);
protected final String COPROCESSORCLASSNAME = "org.apache.hadoop.hbase.coprocessor.AggregateImplementation";
}
HBaseTableCreator.java
public class HBaseTableCreator extends HBaseTableOperatorBase{
private HBaseTableCreatorParms parms;
public void setParms(HBaseTableCreatorParms parms){
this.parms = parms;
}
private HTableDescriptor createHTableDescriptor(){
// 2.表描述
HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(parms.getTableName()));
List<HColumnDescriptor> columnDescriptors = createColumnDescriptors();
columnDescriptors.forEach(hcd->{
htd.addFamily( hcd);
});
for( String coprocessorClassName : parms.getCoprocessorClassNames() ){
try {
htd.addCoprocessor(coprocessorClassName);
} catch (IOException e1) {
LOG.error("为表" + parms.getTableName() + " 添加协处理器失败。 ", e1);
}
}
return htd;
}
private List<HColumnDescriptor> createColumnDescriptors(){
List<HColumnDescriptor> cfs = new ArrayList<>();
parms.getColumFamilies().forEach(x->{
cfs.add(createColumnDescriptor(x));
});
return cfs;
}
private HColumnDescriptor createColumnDescriptor(String columnFamily){
HColumnDescriptor hcd = new HColumnDescriptor(columnFamily);
//定义最大版本号
if( parms.getMaxVersion() > 0 )hcd.setMaxVersions(parms.getMaxVersion());
hcd.setBloomFilterType(BloomType.ROWCOL);
hcd.setInMemory(parms.isInMemory());
hcd.setScope(1);
if(parms.isUseSNAPPY())hcd.setCompressionType(Compression.Algorithm.SNAPPY);
if( parms.getTtl() < 0 ) parms.setTtl(HConstants.FOREVER);
hcd.setTimeToLive(parms.getTtl());
return hcd;
}
public boolean createTable(){
HTableDescriptor htd = createHTableDescriptor();
Admin admin = null;
try {
admin = conf.getHconnection().getAdmin();
if(admin.tableExists(htd.getTableName())){
LOG.info("表" + htd.getTableName() + "已经存在");
}else{
if(parms.getSplits()==null){
admin.createTable(htd);
}else{
admin.createTable(htd,parms.getSplits());
}
}
} catch(IOException e ) {
LOG.error("创建HBase表失败。", e);
return false;
}finally{
try {
if(admin!=null){
admin.close();
}
} catch (IOException e) {
LOG.error("", e);
}
}
return true;
}
}
HBaseTableCreatorParms.java
public class HBaseTableCreatorParms {
private String tableName;
private List<String> columFamilies = new ArrayList();
private boolean inMemory = false;
private int ttl = -1;
private int maxVersion = 1;
private boolean useSNAPPY = true;
private byte[][] splits = null;
private List<String> coprocessorClassNames = new ArrayList();
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public List<String> getColumFamilies() {
return columFamilies;
}
public void setColumFamilies(List<String> columFamilies) {
this.columFamilies.addAll(columFamilies);
}
public void setColumFamilies(String... columFamilies) {
for (String columFamily : columFamilies) {
this.columFamilies.add(columFamily);
}
}
public boolean isInMemory() {
return inMemory;
}
public void setInMemory(boolean inMemory) {
this.inMemory = inMemory;
}
public int getTtl() {
return ttl;
}
public void setTtl(int ttl) {
this.ttl = ttl;
}
public int getMaxVersion() {
return maxVersion;
}
public void setMaxVersion(int maxVersion) {
this.maxVersion = maxVersion;
}
public boolean isUseSNAPPY() {
return useSNAPPY;
}
public void setUseSNAPPY(boolean useSNAPPY) {
this.useSNAPPY = useSNAPPY;
}
public byte[][] getSplits() {
return splits;
}
public void setSplits(byte[][] splits) {
this.splits = splits;
}
public List<String> getCoprocessorClassNames() {
return coprocessorClassNames;
}
public void setCoprocessorClassNames(List<String> coprocessorClassNames) {
this.coprocessorClassNames.addAll(coprocessorClassNames);
}
public void setCoprocessorClassNames(String... coprocessorClassNames) {
for (String coprocessorClassName : coprocessorClassNames) {
this.coprocessorClassNames.add(coprocessorClassName);
}
}
@Override
public String toString() {
return "HBaseTableCreatorParms{" +
"tableName='" + tableName + '\'' +
", columFamilies=" + columFamilies +
", inMemory=" + inMemory +
", ttl=" + ttl +
", maxVersion=" + maxVersion +
", useSNAPPY=" + useSNAPPY +
", coprocessorClassNames=" + coprocessorClassNames +
'}';
}
}
HBaseTableCreatorBuilder.java
public class HBaseTableCreatorBuilder {
private HBaseTableCreatorParms parms = new HBaseTableCreatorParms();
//应该缓存,或者懒加载
public static HBaseTableCreatorBuilder builder(){
return new HBaseTableCreatorBuilder();
}
public HBaseTableCreatorBuilder setTableName(String tableName){
this.parms.setTableName(tableName);
return this;
}
public HBaseTableCreatorBuilder setColumnFamilies(String ...columnFamily){
this.parms.setColumFamilies(columnFamily);
return this;
}
public HBaseTableCreatorBuilder setColumnFamilies(List<String> columnFamily){
this.parms.setColumFamilies(columnFamily);
return this;
}
public HBaseTableCreatorBuilder setInMemory(boolean inMemory){
this.parms.setInMemory(inMemory);
return this;
}
public HBaseTableCreatorBuilder setMaxVersion(int maxVersion){
this.parms.setMaxVersion(maxVersion);
return this;
}
public HBaseTableCreatorBuilder setUseSNAPPY(boolean useSNAPPY){
this.parms.setUseSNAPPY(useSNAPPY);
return this;
}
public HBaseTableCreatorBuilder setSplits(byte[][] splits){
this.parms.setSplits(splits);
return this;
}
public HBaseTableCreatorBuilder setCoprocessorClassNames(String... coprocessorClassNames){
this.parms.setCoprocessorClassNames(coprocessorClassNames);
return this;
}
public HBaseTableCreatorBuilder setCoprocessorClassNames(List<String> coprocessorClassNames){
this.parms.setCoprocessorClassNames(coprocessorClassNames);
return this;
}
// TODO: 8/29 后期优化代码时,要考虑把该对象缓存起来,避免每次创建都new (可以结合原型pattern ,也可以不考虑)
public HBaseTableCreator Create(){
HBaseTableCreator creator = new HBaseTableCreator();
creator.setParms(parms);
return creator;
}
}
测试用例,调用
@Test
public void TestCreateTable(){
boolean success = HBaseTableCreatorBuilder.builder()
.setTableName("test1")
.setColumnFamilies("cf1","cf2")
.Create()
.createTable();
System.out.println(success);
}
@Test
public void TestCreateSplitTable(){
boolean success = HBaseTableCreatorBuilder.builder()
.setTableName("test2")
.setColumnFamilies("info")
.setSplits(SpiltRegionUtil.getSplitKeysByRadom())
.Create()
.createTable();
System.out.println(success);
}
六.总结
通过上述代码可知,Builder模式有助于使代码更加清晰,并且容易拓展。比较适合频繁创建对象的业务场景,但是缺点就是类的数量会变的特别多,建议还是在属性特别多并且可选时使用。
浙公网安备 33010602011771号