深入Java Builder模式--组装复杂的实例

为什么80%的码农都做不了架构师?>>>   hot3.png

#Java Builder模式-组装复杂的实例。

  • 上一面介绍 初探Java Builder模式--组装复杂的实力 简单介绍了下我在项目中的使用。

Builder

  • 什么是Builder模式?

    • ​ 大都市中林立着许多高楼大厦,这些高楼大厦都是具有建筑结构的大型建筑。通常,建造和构建这种具有建筑结构的大型物体在英文中成为Build。

      ​ 在建筑大楼时,需要打牢地基,搭建框架,然后自下而上地一层一层盖起来。通常,在建造这种具有复杂结构的物体时,很难一气呵成。我们需要首先建造组成这个物体的各个部分,然后分段将他们组装起来。

      ​ ---图解设计模式

  • 这个用例并不是特别的明显,大体的思路是这样的。

  • 改造上次的代码。首先分析下上篇文章中ztree的数据结构

深入Java Builder模式--组装复杂的实例_第1张图片

  • 依赖库
    • commons-lang3
      • 3.4
    • com.thoughtworks.xstream
      • 1.4.10
    • com.fasterxml.jackson.core
      • 2.8.1

Builder中角色

关系大概就是这样的样子

  • 建造者 Builder
  • 具体建造者ConcreteBuilder
    • ZtreeJSONBuilder
    • ZtreeXMLBuilder
  • 监工 Director
  • 测试 Testing
participant Testing
participant Director
participant ConstructBuilder
Testing -> ConstructBuilder: new
Testing -> Director : construct
Director -> ConstructBuilder : init
ConstructBuilder -->> Director : 
Director-->> Testing: successful

深入Java Builder模式--组装复杂的实例_第2张图片

Builder建造者


package cn.z201.gof.builder;

 import java.util.Collection;

 public abstract class ZtreeBuilder {
 	public static final String TOP = "0001";
 	
 	public abstract String treeName();
 	
 	public abstract Object findResuls();
 	
 	public abstract void id(String id);
 	
 	public abstract void pid(String pid);
 	
 	public abstract void name(String name);
 	
 	public abstract void url(String url);
 	
 	public abstract void open(boolean open);
 	
 	public abstract void parent(boolean parent);
 	
 	public abstract void children(Collection children);
 	
 	public abstract String id();
 	
 	public abstract String pid();
 	
 	public abstract String name();
 	
 	public abstract String url();
 	
 	public abstract boolean open();
 	
 	public abstract boolean parent();
 	
 	public abstract Collection children();
 	
 	
 }


ConcreteBuilder具体的建造者

  package cn.z201.gof.builder;

  import java.util.ArrayList;
  import java.util.Collection;

  import cn.z201.gof.utils.JsonUtil;

  public class ZtreeJSONBuilder extends ZtreeBuilder{
  	
      //本级Id
      private String id; 
      //父级菜单的 id
      private String pid; 
      //中文名称
      private String name; 
      //点击地址
      private String url; 
      //是否展开
      private boolean open; 
      //是否为父节点
      private boolean isParent; 
      
      private Collection children = new ArrayList();;
      
  	public ZtreeJSONBuilder() {
  		
  	}
      
  	@Override
  	public String treeName() {
  		return this.getClass().getSimpleName();
  	}
  	
      @Override
      public Object findResuls(){
      	return JsonUtil.toJson(this);
      }
  	
  	@Override
  	public void id(String id) {
  		this.id = id;
  	}

  	@Override
  	public void pid(String pid) {
  		this.pid = pid;
  	}

  	@Override
  	public void name(String name) {
  		this.name = name;
  	}

  	@Override
  	public void url(String url) {
  		this.url = url;
  	}

  	@Override
  	public void open(boolean open) {
  		this.open = open;
  	}

  	@Override
  	public void parent(boolean isParent) {
  		this.isParent = isParent;
  	}

  	@Override
  	public void children(Collection children) {
  		this.children = (Collection) children;
  	}
  	
  	@Override
  	public String id() {
  		return this.id;
  	}

  	@Override
  	public String pid() {
  		return this.pid;
  	}

  	@Override
  	public String name() {
  		return this.name;
  	}

  	@Override
  	public String url() {
  		return this.url;
  	}

  	@Override
  	public boolean open() {
  		return this.open;
  	}

  	@Override
  	public boolean parent() {
  		return this.isParent;
  	}

  	@Override
  	public Collection children() {
  		return this.children;
  	}

  	public String getId() {
  		return id;
  	}

  	public void setId(String id) {
  		this.id = id;
  	}

  	public String getPid() {
  		return pid;
  	}

  	public void setPid(String pid) {
  		this.pid = pid;
  	}

  	public String getName() {
  		return name;
  	}

  	public void setName(String name) {
  		this.name = name;
  	}

  	public String getUrl() {
  		return url;
  	}

  	public void setUrl(String url) {
  		this.url = url;
  	}

  	public boolean isOpen() {
  		return open;
  	}

  	public void setOpen(boolean open) {
  		this.open = open;
  	}

  	public boolean getIsParent() {
  		return isParent;
  	}

  	public void setIsParent(boolean isParent) {
  		this.isParent = isParent;
  	}

  	public Collection getChildren() {
  		return children;
  	}

  	public void setChildren(Collection children) {
  		this.children = children;
  	}

  }
  package cn.z201.gof.builder;

  import java.util.ArrayList;
  import java.util.Collection;

  import com.thoughtworks.xstream.XStream;
  import com.thoughtworks.xstream.annotations.XStreamAlias;

  import cn.z201.gof.utils.XMLUtil;

  @XStreamAlias("ZtreeXMLBuilder")  
  public class ZtreeXMLBuilder extends ZtreeBuilder{
  	 //本级Id
      private String id; 
      //父级菜单的 id
      private String pid; 
      //中文名称
      private String name; 
      //点击地址
      private String url; 
      //是否展开
      private boolean open; 
      //是否为父节点
      private boolean isParent; 
      
      private Collection children = new ArrayList();
      
  	public ZtreeXMLBuilder() {
  	}
      
  	@Override
  	public String treeName() {
  		return this.getClass().getSimpleName();
  	}
  	
      @Override
      public Object findResuls(){
      	XStream xstream = new XStream();
      	xstream.autodetectAnnotations(true);  
      	xstream.alias("ZtreeXMLBuilder", ZtreeXMLBuilder.class);  
      	xstream.registerConverter(new XMLUtil());  
      	return xstream.toXML(this);
      }
  	
  	@Override
  	public void id(String id) {
  		this.id = id;
  	}

  	@Override
  	public void pid(String pid) {
  		this.pid = pid;
  	}

  	@Override
  	public void name(String name) {
  		this.name = name;
  	}

  	@Override
  	public void url(String url) {
  		this.url = url;
  	}

  	@Override
  	public void open(boolean open) {
  		this.open = open;
  	}

  	@Override
  	public void parent(boolean isParent) {
  		this.isParent = isParent;
  	}

  	@Override
  	public void children(Collection children) {
  		this.children = (Collection) children;
  	}
  	
  	@Override
  	public String id() {
  		return this.id;
  	}

  	@Override
  	public String pid() {
  		return this.pid;
  	}

  	@Override
  	public String name() {
  		return this.name;
  	}

  	@Override
  	public String url() {
  		return this.url;
  	}

  	@Override
  	public boolean open() {
  		return this.open;
  	}

  	@Override
  	public boolean parent() {
  		return this.isParent;
  	}

  	@Override
  	public Collection children() {
  		return this.children;
  	}

  	public String getId() {
  		return id;
  	}

  	public void setId(String id) {
  		this.id = id;
  	}

  	public String getPid() {
  		return pid;
  	}

  	public void setPid(String pid) {
  		this.pid = pid;
  	}

  	public String getName() {
  		return name;
  	}

  	public void setName(String name) {
  		this.name = name;
  	}

  	public String getUrl() {
  		return url;
  	}

  	public void setUrl(String url) {
  		this.url = url;
  	}

  	public boolean getOpen() {
  		return open;
  	}

  	public void setOpen(boolean open) {
  		this.open = open;
  	}

  	public boolean getIsParent() {
  		return isParent;
  	}

  	public void setIsParent(boolean isParent) {
  		this.isParent = isParent;
  	}

  	public Collection getChildren() {
  		return children;
  	}

  	public void setChildren(Collection children) {
  		this.children = children;
  	}

  	
  }


Director监工

  package cn.z201.gof.builder;



  import cn.z201.gof.utils.CodingFactoryUtil;

  public class Director{
  	
  	private ZtreeBuilder ztreeBuilder;
  	
  	public > Director(ZtreeBuilder builder){
  		ztreeBuilder = builder;
  	}
  	
  	public Object getResuls(){
  	    return  ztreeBuilder.findResuls();
  	}
  	
  	public void  construct(){
  		if(null == ztreeBuilder.id()){
  			ztreeBuilder.id(ZtreeBuilder.TOP);
  		}
  		
  		if(null == ztreeBuilder.name()){
  			ztreeBuilder.name(ztreeBuilder.treeName());
  		}
  		
  		if(null == ztreeBuilder.pid()){
  			ztreeBuilder.pid(CodingFactoryUtil.ztreeCodingFactory(ZtreeBuilder.TOP, ZtreeBuilder.TOP));
  		}else{
  			ztreeBuilder.pid(CodingFactoryUtil.ztreeCodingFactory(ztreeBuilder.pid(), ztreeBuilder.id()));
  		}
  	}

  }


工具类


package cn.z201.gof.utils;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;


public class CodingFactoryUtil {
	
	private static final Logger LOGGER = Logger.getLogger(CodingFactoryUtil.class);
	
	/** ztree的编码加工规则 */
	public static final int ztreeRules = 4;
	
	/** 补码 */
	public static final String complement = "0";
	
	/**
	 * @param head 前置编码 比如0001
	 * @param tail 后置编码 比如1
	 * @param reules 编码长度 比如4 表示长度四位
	 * @return 00010001
	 * @throws Exception 
	 */
	public static String codingFactory(String head ,String tail ,int reules) throws Exception{
		if(tail.length() > reules) throw new Exception();
		for (int i = 0; i < reules; i++) {
			if(tail.length() == reules) break;
			tail = StringUtils.join(complement , tail);
		}
		return StringUtils.join(head , tail);
	}
	
	public static String ztreeCodingFactory(String head , String tail){
		try {
			return codingFactory(head , tail , ztreeRules);
		} catch (Exception e) {
			LOGGER.error(e.getMessage());
		}
		return null;
	}
	
}
package cn.z201.gof.utils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

/**
 * JSON 和 Java对象相互转换
 */
public class JsonUtil {

    private static final ObjectMapper objectMapper;

    static {
        objectMapper = new ObjectMapper();

        //去掉默认的时间戳格式
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

        //设置为中国上海时区
        objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        objectMapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);

        //空值不序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);

        //反序列化时,属性不存在的兼容处理
        objectMapper.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        //序列化时,日期的统一格式
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        //单引号处理
        objectMapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        objectMapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
        //objectMapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.CANONICALIZE_FIELD_NAMES, true);
    }

    public static  T toObject(String json, Class clazz) {
        try {
            return objectMapper.readValue(json, clazz);
        } catch (JsonParseException e) {
            throw new MepException(e);
        } catch (JsonMappingException e) {
            throw new MepException(e);
        } catch (IOException e) {
            throw new MepException(e);
        }
    }

    public static  T toCollection(String json, TypeReference typeReference) {
        try {
            return objectMapper.readValue(json, typeReference);
        } catch (JsonParseException e) {
            throw new MepException(e);
        } catch (JsonMappingException e) {
            throw new MepException(e);
        } catch (IOException e) {
            throw new MepException(e);
        }
    }

    public static  String toJson(T entity) {
        try {
            return objectMapper.writeValueAsString(entity);
        } catch (JsonGenerationException e) {
            throw new MepException(e);
        } catch (JsonMappingException e) {
            throw new MepException(e);
        } catch (IOException e) {
            throw new MepException(e);
        }
    }
}

/**  
 * Copyright © 2017 z201.cn . All rights reserved.
 * @Title: XMLUtil.java
 * @Prject: learn-gof
 * @Package: cn.z201.gof.utils
 * @author: [email protected]
 * @date: 2017年7月15日 上午3:51:36
 */
package cn.z201.gof.utils;

import java.lang.reflect.Field;  
import java.lang.reflect.Method;  
import java.lang.reflect.ParameterizedType;  
import java.lang.reflect.Type;  
import java.util.Arrays;  
import java.util.Collection;  
import java.util.List;  
import java.util.Set;  
  
import com.thoughtworks.xstream.converters.Converter;  
import com.thoughtworks.xstream.converters.MarshallingContext;  
import com.thoughtworks.xstream.converters.UnmarshallingContext;  
import com.thoughtworks.xstream.io.HierarchicalStreamReader;  
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;  

public class XMLUtil  implements Converter{  
	 @SuppressWarnings("rawtypes")  
	    private Class currentType;  
	    private final String clazzNames[] = {"ZtreeXMLBuilder"};// 定义所要转换的对象及所包含的对象名称  
	    private List clazzNamesList;  
	  
	    @SuppressWarnings("rawtypes")  
	    @Override  
	    public boolean canConvert(Class type) {  
	        currentType = type;  
	        clazzNamesList = Arrays.asList(clazzNames);  
	        if (clazzNamesList.contains(currentType.getSimpleName())) {  
	            return true;  
	        } else {  
	            return false;  
	        }  
	    }  
	  
	    @Override  
	    public void marshal(Object source, HierarchicalStreamWriter writer,  
	            MarshallingContext context) {  
	        try {  
	            marshalSuper(source, writer, context, currentType);  
	        } catch (Exception e) {  
	            e.printStackTrace();  
	  
	        }  
	    }  
	  
	    @SuppressWarnings({ "unchecked", "rawtypes" })  
	    private Object getObj(Class clazz, String nodeName, Object source)  
	            throws Exception {  
	        Method method = clazz.getMethod("get"  
	                + Character  
	                        .toUpperCase(nodeName.substring(0, 1).toCharArray()[0])  
	                + nodeName.substring(1));  
	        Object obj = null;  
	        obj = method.invoke(clazz.cast(source), new Object[0]);  
	        return obj;  
	    }  
	  
	    @SuppressWarnings({ "rawtypes" })  
	    private void objConverter(Object source, HierarchicalStreamWriter writer,  
	            MarshallingContext context, Class clazz, String nodeName,  
	            Class fieldClazz) throws Exception {  
	        Object obj = getObj(clazz, nodeName, source);  
	        writer.startNode(nodeName);  
	        marshalSuper(obj, writer, context, fieldClazz);  
	        writer.endNode();  
	    }  
	  
	    @SuppressWarnings({ "rawtypes" })  
	    private void collectionConverter(Object source,  
	            HierarchicalStreamWriter writer, MarshallingContext context,  
	            Class clazz, String nodeName, Field field) throws Exception {  
	        Type types[] = ((ParameterizedType) field.getGenericType())  
	                .getActualTypeArguments();  
	        Object obj = getObj(clazz, nodeName, source);  
	        Collection collection = null;  
	        if (field.getType().equals(List.class)) {  
	            collection = (List) obj;  
	        } else if (field.getType().equals(Set.class)) {  
	            collection = (Set) obj;  
	        }  
	        writer.startNode(nodeName);  
	        for (Object object : collection) {  
	            String clazzName = ((Class) types[0]).getSimpleName();  
	            writer.startNode(Character.toLowerCase(clazzName.substring(0, 1)  
	                    .toCharArray()[0]) + clazzName.substring(1));  
	            marshalSuper(object, writer, context, (Class) types[0]);  
	            writer.endNode();  
	        }  
	        writer.endNode();  
	    }  
	  
	    @SuppressWarnings({ "rawtypes" })  
	    private void basicTypeConverter(Object source,  
	            HierarchicalStreamWriter writer, MarshallingContext context,  
	            Class clazz, String nodeName) throws Exception {  
	        Object obj = getObj(clazz, nodeName, source);  
	        writer.startNode(nodeName);  
	        writer.setValue(obj == null ? "" : obj.toString());  
	        writer.endNode();  
	    }  
	  
	    @SuppressWarnings({ "rawtypes" })  
	    private void marshalSuper(Object source, HierarchicalStreamWriter writer,  
	            MarshallingContext context, Class clazz) throws Exception {  
	        Field fields[] = clazz.getDeclaredFields();  
	        for (Field field : fields) {  
	            String nodeName = field.getName();  
	            Class fieldClazz = field.getType();  
	            if (clazzNamesList.contains(fieldClazz.getSimpleName())) {  
	                objConverter(source, writer, context, clazz, nodeName,  
	                        fieldClazz);  
	            } else if (Arrays.asList(fieldClazz.getInterfaces()).contains(  
	                    Collection.class)) {  
	                collectionConverter(source, writer, context, clazz, nodeName,  
	                        field);  
	            } else {  
	                basicTypeConverter(source, writer, context, clazz, nodeName);  
	            }  
	        }  
	    }  
	  
	    @Override  
	    public Object unmarshal(HierarchicalStreamReader reader,  
	            UnmarshallingContext context) {  
	        return null;  
	    }  
}

测试

package cn.z201.gof;

import org.junit.Test;


import cn.z201.gof.builder.Director;
import cn.z201.gof.builder.ZtreeBuilderXML;
import cn.z201.gof.builder.ZtreeBuilderJSON;


public class Testing {

	@Test
	public void test(){
		Director director = new Director(new ZtreeJSONBuilder());
		director.construct();
		System.out.println(director.getResuls());
			director = new Director(new ZtreeXMLBuilder());
			director.construct();
		System.out.println(director.getResuls());
		
	}
	
}

测试结果

  • 这里做了区分,所以使用了两种数据形式展示。
{"id":"0001","pid":"00010001","name":"ZtreeJSONBuilder","url":null,"open":false,"isParent":false,"children":[]}

  0001
  00010001
  ZtreeXMLBuilder
  
  false
  false
  []

转载于:https://my.oschina.net/z201/blog/1396654

你可能感兴趣的:(深入Java Builder模式--组装复杂的实例)