建造者模式
这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式,使用多个简单的对象一步一步构建成一个复杂的对象。
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
关键代码:建造者-->创建和提供实例,导演-->管理建造出来的实例的依赖关系。
优点:建造者独立、易扩展,便于控制细节风险。
缺点:产品必须有共同点,范围有限制,如果内部变化复杂,会有很多的建造类。
实例:
我们新建一个人的类。
public class Human { //构造一个人的基本属性 private String head; private String body; private String hand; private String foot; //这里用于打印通过我们造出一个人的基本属性 public void show(){ System.out.println(head); System.out.println(body); System.out.println(hand); System.out.println(foot); } public String getHead() { return head; } public void setHead(String head) { this.head = head; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public String getHand() { return hand; } public void setHand(String hand) { this.hand = hand; } public String getFoot() { return foot; } public void setFoot(String foot) { this.foot = foot; } }
只要是一个人,都是从这个类出来的。(基本类)
一个人的基本属性我们定下来了,但是造人的话,得要规定一个标准吧。所以我们先写一个接口,定义一个造人标准接口。
public interface IHuman { //构造人的方法 void buildHead();//构造人的头 void buildBody();//构造人的身体 void buildHand();//构造人的手 void buildFoot();//构造人的脚 Human createHuman();//返回一个我们想要构造的人 }
现在,根据我们定的人的基本属性和造人标准,来造一个胖的人。
public class FatBuildHuman implements IHuman {//这个胖人类实现造人的接口 Human human; public FatBuildHuman (){ human =new Human(); } @Override public void buildHead() { human.setHead("胖人的头"); } @Override public void buildBody() { human.setBody("胖人的身体"); } @Override public void buildHand() { human.setHand("胖人的手"); } @Override public void buildFoot() { human.setFoot("胖人的脚"); } @Override public Human createHuman() { return human;//返回我们构造的人 } }
到这里呢,我们已经完成了建造的过程,接下来,就是介绍构建者模式的精髓,director 这个director,就是来执行我们刚才的造人动作,可以简单理解为 指挥员 。
public class Director { public Human create(IHuman iHuman){// iHuman.buildHead(); iHuman.buildBody(); iHuman.buildHand(); iHuman.buildFoot(); return iHuman.createHuman(); } }
这个Director类,重点在于create方法的参数是我们刚才定义的造人标准接口,只要是实现了我们的这个接口的类,就都可以作为参数。
现在我们来看看Director是如何发挥它的指挥能力的。
public class Test { public static void main(String[] args) { Director director = new Director(); Human human = director.create(new FatBuildHuman()); human.show(); } }
结果:
1 胖人的头 2 胖人的身体 3 胖人的手 4 胖人的脚
现在我们再来造一个 高智商头脑、强壮的身体、灵活的小手、有点肥的脚 的人出来。
先建一个名为TestHuan的类出来,并且实现 我们刚刚 定义的 造人标准接口。
public class TestHuman implements IHuman { Human human; public TestHuman(){ human = new Human(); } @Override public void buildHead() { human.setHead("高智商的头脑"); } @Override public void buildBody() { human.setBody("强壮的身体"); } @Override public void buildHand() { human.setHand("灵活的小手"); } @Override public void buildFoot() { human.setFoot("有点肥的脚"); } @Override public Human createHuman() { return human; } }
同样的通过Director类 来 指挥:
public class Test { public static void main(String[] args) { Human human1 = director.create(new TestHuman()); human1.show(); } }
结果:
1 高智商的头脑 2 强壮的身体 3 灵活的小手 4 有点肥的脚
Director类,重点在于create方法的参数是我们刚才定义的造人标准接口,只要是实现了我们的这个接口的类,就都可以作为参数。
建造者模式就是这样。那到最后,我们必须要思考一下为什么这么做?学而不思则罔,我们纵观全部代码,其实我们就会发现,在最后的Test类中,我们其实根本就不会知道具体是怎么造人的,因为这个过程让Director给代劳了。然后,我们的FatBuildHuman类中才是真正的造人方法。Director其实只是执行了这个过程。这样子,达到了分离模块的功能。造人的过程,启动造人的过程,和最后选择哪种人来造。都分的清清楚楚。就有了一些模块化的感觉,这样维护和扩展都是很方便的。
另一个示例代码:
package mass.resultDemo; import com.github.pagehelper.Page; import java.util.ArrayList; import java.util.List; public class ResultVo<T>{ private int code; private String errMsg; private T data; private Page<T> pager; private List<ErrorDetail> errors; private long dataTimestamp; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getErrMsg() { return errMsg; } public void setErrMsg(String errMsg) { this.errMsg = errMsg; } public T getData() { return data; } public void setData(T data) { this.data = data; } public Page<T> getPager() { return pager; } public void setPager(Page<T> pager) { this.pager = pager; } public List<ErrorDetail> getErrors() { return errors; } public void setErrors(List<ErrorDetail> errors) { this.errors = errors; } public long getDataTimestamp() { return dataTimestamp; } public void setDataTimestamp(long dataTimestamp) { this.dataTimestamp = dataTimestamp; } // director public static ResultBuilder status(int code){ ResultBuilder builder = new DefaultBuilder<>(); builder.status(code); return builder; } public static ResultBuilder addError(String type, String message) { ResultBuilder builder = new DefaultBuilder<>(); builder.addError(type, message); return builder; } public static ResultVo ok(Object data){ ResultBuilder builder = new DefaultBuilder<>(); return builder.data(data); } public static ResultVo ok(Object data, Page page){ ResultBuilder builder = new DefaultBuilder<>(); return builder.data(data); } public static ResultVo err(int code,String errMsg){ return null; } @Override public String toString() { return "ResultVo{" + "code=" + code + ", errMsg='" + errMsg + '\'' + ", data=" + data + ", pager=" + pager + ", errors=" + errors + ", dataTimestamp=" + dataTimestamp + '}'; } // 函数的类型签名 public interface ResultBuilder<T> { ResultBuilder addError(String type, String message); ResultBuilder status(int status); ResultVo<T> data(T data); ResultVo<T> data(int status, T data); ResultVo<T> err(int status); ResultVo<T> err(int status, String emsg); } public static class DefaultBuilder<T> implements ResultBuilder<T> { private ResultVo<T> resultVo; public DefaultBuilder() { this.resultVo = new ResultVo<T>(); } @Override public ResultBuilder addError(String type, String message) { if(resultVo.getErrors() == null) { resultVo.setErrors(new ArrayList<>()); } ErrorDetail detail = new ErrorDetail(); detail.setType(type); detail.setMessage(message); resultVo.getErrors().add(detail); return this; } @Override public ResultBuilder status(int status) { resultVo.setCode(status); return this; } @Override public ResultVo<T> data(T data) { return null; } @Override public ResultVo<T> data(int status, T data) { // status 200 this.status(status); resultVo.setData(data); return resultVo; } @Override public ResultVo<T> err(int status) { return null; } @Override public ResultVo<T> err(int status, String emsg) { return null; } } } class ErrorDetail { private String type; private String message; public String getType() { return type; } public void setType(String type) { this.type = type; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
测试:
package mass.resultDemo; import com.github.pagehelper.Page; import java.util.ArrayList; public class TestResult { public static void main(String[] args) { ResultVo resultVo_1 = ResultVo.ok("正常返回"); ResultVo resultVo = new ResultVo(); ArrayList<ErrorDetail> list = new ArrayList<>(); list.add(new ErrorDetail()); list.add(new ErrorDetail()); list.add(new ErrorDetail()); list.add(new ErrorDetail()); list.add(new ErrorDetail()); list.add(new ErrorDetail()); resultVo.setErrors(list); ResultVo resultVo_2 = ResultVo.ok("带分页信息返回", new Page()); ResultVo resultVo_3 = ResultVo.status(201).data("正常返回"); ResultVo resultVo_4 = ResultVo.err(400, "数据错误"); ResultVo resultVo_5 = ResultVo.status(400).err("数据错误"); ResultVo resultVo_6 = ResultVo .addError(new ErrorDetail("RunTimeException",555)) .addError("RunTimeException",500) .addError(new ErrorDetail()) .err(411); } }