ningendo

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模式有助于使代码更加清晰,并且容易拓展。比较适合频繁创建对象的业务场景,但是缺点就是类的数量会变的特别多,建议还是在属性特别多并且可选时使用。

posted on 2020-09-07 15:17  Lunamonna  阅读(98)  评论(0编辑  收藏  举报

导航