Builder模式主要用来一步一步创建一个复杂对象的创建模式。主要用来创建对象,它允许客户端不知道内存的创建的具体过程的情况下去生成一个对象。
感谢
Builder模式的误区:将复杂对象的构建进行封装,就是Builder模式了吗?
Builder模式的uml图
- Builder: 抽象的builder的类,规范产品的组建。一般有子类去实现具体的组建过程。
- ConcreteBuilderA ConcreteBuilderB:具体的构建类。
- Director:同一的装配的过程。
关键点
- 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
- 创建的复杂的对象的算法应该独立于该对象的组成部分以及其装配的方法,
- builder模式多处理是用来的聚合的观念,而不是继承的观念
- 不同的product类的组成的过程中,不能进行组合和替换
举个栗子
product类
person 类
public abstract class Person {
protected Hand mHand;
protected Foot mFoot;
protected Head mHead;
protected Body mBody;
public abstract void setHand(Hand hand);
public abstract void setFoot(Foot foot);
public abstract void setHead(Head head);
public abstract void setBody(Body body);
}
组装的part类
Body类
public abstract class Body {
}
Head类
public abstract class Head {
}
Hand类
public abstract class Hand {
}
Foot类
public abstract class Foot {
}
builder类
public abstract class Builder {
protected Person mPerson;
public abstract void buildHead(Head head);
public abstract void buildBody(Body body);
public abstract void buildHand(Hand hand);
public abstract void buildFoot(Foot foot);
public Person build(){
System.out.println("创建一个person了");
return mPerson;
}
}
PersonDirector导向类
public class PersonDirector {
private Builder mBuilder = null;
public PersonDirector(Builder builder){
mBuilder = builder;
}
public Person createPerson(Head head,Hand hand,Foot foot,Body body){
mBuilder.buildFoot(foot);
mBuilder.buildHead(head);
mBuilder.buildHand(hand);
mBuilder.buildBody(body);
return mBuilder.build();
}
}
从上述的构建基层的情况下,类和类之间的耦合程度较低,所以方便的扩张,简单说明下我们上面的创建,首先我们的需求是:我们需要创建一个比较复杂的person类的对象,在person中我们需要需许多的part,比如head,hand,foot等。这个时候就非常符合builder模式,将对象的创建和表示层给分开。比如此时我们需要创建一个human人类的时候。我们需要创建的类
Human Part 类
public class HumanBody extends Body{
public HumanBody(){
System.out.println("这是个人类的身体");
}
}
public class HumanFoot extends Foot{
public HumanFoot(){
System.out.println("这是个人类的腿");
}
}
public class HumanHand extends Hand{
public HumanHand(){
System.out.println("这是个人类的胳膊");
}
}
public class HumanHead extends Head{
public HumanHead(){
System.out.println("这是个人类的头");
}
}
Human类
public class Human extends Person {
@Override
public void setHand(Hand hand) {
mHand = hand;
}
@Override
public void setFoot(Foot foot) {
mFoot = foot;
}
@Override
public void setHead(Head head) {
mHead = head;
}
@Override
public void setBody(Body body) {
mBody = body;
}
}
HumanBuilder
public class HumanBuilder extends Builder {
public HumanBuilder(){
mPerson = new Human();
}
@Override
public void buildHead(Head head) {
System.out.println("装配上人类的头");
mPerson.setHead(head);
}
@Override
public void buildBody(Body body) {
System.out.println("装配上人类的身体");
mPerson.setBody(body);
}
@Override
public void buildHand(Hand hand) {
System.out.println("装配上人类的手");
mPerson.setHand(hand);
}
@Override
public void buildFoot(Foot foot) {
System.out.println("装配上人类的脚");
mPerson.setFoot(foot);
}
}
接下来的们在client类中会创建一个Human类
public class client {
public static void main(String[] args) {
// 创建所需要的part类
Foot foot = new HumanFoot();
Head head = new HumanHead();
Body body = new HumanBody();
Hand hand = new HumanHand();
//创建builder类
Builder builder = new HumanBuilder();
//创建director类
PersonDirector personDirector = new PersonDirector(builder);
personDirector.createPerson(head, hand, foot, body);
}
}
打印出的log为:
上面就算是一个完整builder模式的栗子了,但是接下来我们的需要说明一些的builder模式的特别的地方以及应该注意的地方。
builder需要注意的地方
builder模式多处理是用来的聚合的观念,而不是继承的观念
builder模式主要是用来创建复杂的对象,从而实现对对象的创建过程和表示层实现分离。主要是方便后续开发的理解。上面的栗子是当我们去创建一个Humand的时候,如果这个时候我们再去创建一个Robet类的话,同样的,我们也需要去创建的RobetBuilder类。在RebotBuilder类中,我们需要对RebotBuilder类去装配相应的Head,Hand,Foot,body等part类。从而实现一个的完整的robet。这些都是一些无可非议的。这样似乎我在创建的一个新的Person类的时候,我只需要的实现的新的Builder类就可以了,但是真的是这样子的吗?比如说我现在的想实现一个瘦的Human类,我是不是需要再去实现一个新的ThinHumanBuilder类。然后给他装配上相应的ThinHead,ThinHand,ThinBody,ThinFoot等这些part对象,然后形成一个的ThinHuman。等等?我们会发现到这里的时候,这个时候更像一个模版模式了,而不是builder模式,这个时候,似乎是父类给我们制定相应逻辑流程,然后由具体的子类去实现不同的算法逻辑。这个时候,我们需要考虑下builder模式到底真正的含义是什么?
针对上面的问题,我们需要思考的是,Builder模式更多用来处理组合和聚合这类的问题,而不是继承的问题。如果实际的过程我们需要的创建一个的复杂的对象的时候,针对这个具体复杂的对象的时候,我们需要在其创建的过程的这个小地方的使用builder模式。所以我们更多是将对象的之间没有存在明显的继承关系实现Builder模式。比如说Rebot和Human,至于FatHuman和ThinHuman的更多是属于Human,它们之间是存在明显的继承关系。如果我们的对FatHuman或者ThinHuman都实现Builder模式,那么此时Builder模式似乎变成的了一种为了构建复杂对象的模版模式了。
builder模式uml图中,组合不同数量的现有part
举个例子,针对上面的情况,比如我们现在需要创建一个Alien,为了说明Alien的不同于Human的时候,我们假设它的腿有多个,有的Alien有3个腿,有的5个腿,有个的很多腿,好吧就到这儿,我们采用Builder模式的时候,Alien 和Human其实并没有明显的继承关系,所以很明显的我们需要的创建一个 AlienBuilder类,
public class AlienBuilder extends Builder {
public AlienBuilder(){
mPerson = new Alien();
}
@Override
public void buildHead(Head head) {
System.out.println("装配上Alien的头");
mPerson.setHead(head);
}
@Override
public void buildBody(Body body) {
System.out.println("装配上Alien的身体");
mPerson.setBody(body);
}
@Override
public void buildHand(Hand hand) {
System.out.println("装配上Alien的手");
mPerson.setHand(hand);
}
@Override
public void buildFoot(Foot foot) {
System.out.println("装配上Alien的脚");
mPerson.setFoot(foot);
}
}
这样的话我们就可以创建的Alien。接下来我们面临的就是创建3双腿的Alien.仔细对Builder的模式进行的分析来说。
1. Builder类负责的复杂对象的组成部分的装载
2. Director类负责了复杂对象的装配的过程 在上面的装配的过程中我们看到我们仅仅装配了一双腿,这也就是我们无论怎么创建Person的都是一双腿的,
public Person createPerson(Head head,Hand hand,Foot foot,Body body){
mBuilder.buildFoot(foot);
mBuilder.buildHead(head);
mBuilder.buildHand(hand);
mBuilder.buildBody(body);
return mBuilder.build();
}
我们现在需要装配的3双腿的Alien,我们不能够去重新创建一个的6LegsAlienBuidler去生成6LegsAlien的,我们应该将装配的过程在重新的规划。我们应该将创建对象的算法(脚的个数)独立于对象的组成部分(Builder去管理)以及他们的装配的过程(具体创建6个腿person的过程)。
PersonDirector导向类
public Person createPerson(Head head,Hand hand,Foot foot,Body body,int legCounts){
for(int i = 0;i < legCount;i++){
mBuilder.buildFoot(foot);
}
mBuilder.buildHead(head);
mBuilder.buildHand(hand);
mBuilder.buildBody(body);
return mBuilder.build();
}
Client
public class client {
public static void main(String[] args) {
// 创建所需要的part类
Foot foot = new AlienFoot();
Head head = new AlienHead();
Body body = new AlienBody();
Hand hand = new AlienHand();
//创建builder类
Builder builder = new AlienBuilder();
//创建director类
PersonDirector personDirector = new PersonDirector(builder);
//具体
personDirector.createPerson(head, hand, foot, body);
}
}
经过上述的处理就可以满足的我们的需求
总结
builder模式的主要用来构建复杂的对象,实现对象的构建和表示的分离。
1. Builder类负责的复杂对象的组成部分的装载
2. Director类负责了复杂对象的装配的过程
使用场景
- 可以用来隐藏构建对象的细节。
- 用户仅需在对象的构建的过程中去修改其属性,而不允许客户端在任何地方修改其属性。