Java设计模式之创建者模式

创建者模式一般用于,当一个类的内部数据过于复杂的时候(比如各个属性在设置值的什么要写一大坨代码才可以完成),并且还创建这样的对象不是一个,而是根据不同场景创建多种,并且属性类型基本一样,这个时候就想啊想一种什么法子来管理一下这个类中的数据呢,怎么在创建的时候让它按部就班的来,并且代码可读性很好别让我看花了眼啊,我要的东西也能都很好设置进来,这就是Builder模式的应用场景,Builder模式可以将一个类的构建和表示进行分离。

正文

在看正文前我继续给大家模拟一个生活场景,通俗的为大家解释什么是创建者。

场景:一个暴发户找一家建筑设计公司设计一栋商业和一栋住宅,我们假设这是两个对象,商业和住宅都有相同的属性,比如材料、楼层、结构等,设计公司把图纸和需求给了施工单位,施工单位按照要求完成了施工,交给设计公司一栋商业和一栋住宅,设计公司很满意,把这两个对象交给了暴发户。不考虑实际情况,在上面的场景里,暴发户根本不用操心这个楼是哪个施工单位,那个工人一砖一瓦建成的,他只关注跟设计公司提的需求,设计公司就要满足他,所以该过程屏蔽了用户和建造过程的细节。

所以,我们总结出构建者模式

适用场景

对复杂对象的创建和使用进行隔离。

多个部件都可以装配到一个对象中,但产生的运行结果不相同。

对象非常复杂或者对象因为调用顺序不同而产生不同作用。

初始化一个对象时,参数过多,或者很多参数具有默认值。

适合创建差异性很小的对象,对象具备很强共性。

主要作用

用户不必关心对象的建造过程和细节的情况下就可以直接创建复杂的对象。

方便用户创建很多类似或者说相同属性对复杂对象。

代码复用性 & 封装性。

建造者模式的主要角色

产品角色(Product):它是包含多个组成部件的复杂对象和属性,是一个模型。

抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口或者抽象类,通常还包含一个返回复杂产品的方法 ,该方法一般是抽象并且返回值类型是产品角色(Product)。

具体建造者(Concrete Builder):实现 Builder 接口或者继承Builder 抽象类,完成复杂产品的各个部件的具体创建方法。

指挥者(Director):它调用建造者(Builder)中的部件构造与装配方法完成复杂对象的创建,不设计产品具体构建细节。

示例代码

产品角色(Product)

//实际是你想创建的对象
public class People {
   //这个对象需要的属性,例如创建一个汽车,汽车有发动机,轮子,底盘等
   private String head;
   private String body;
   private String hand;
   private String 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;
   }

   @Override
   public String toString() {
       return "People{" +
               "head='" + head + '\'' +
               ", body='" + body + '\'' +
               ", hand='" + hand + '\'' +
               ", foot='" + foot + '\'' +
               '}';
  }


抽象建造者(Builder)

public abstract class Builder {
   abstract void buildHead();

   abstract void buildBody();

   abstract void buildHand();

   abstract void buildFoot();

   abstract People createPeople();
}

具体建造者(Concrete Builder)一

public class ManBuilder extends Builder {
   private People people = new People();

   void buildHead() {
       people.setHead("男人的头");
   }

   void buildBody() {
       people.setBody("男人的身体");
   }

   void buildHand() {
       people.setHand("男人的手");
   }

   void buildFoot() {
       people.setFoot("男人的脚");
   }

   People createPeople() {
       return people;
   }
}

具体建造者(Concrete Builder)二

public class WomanBuilder extends Builder {
   //声明我们要构建的对象
   private People people = new People();

//下面是对象里的属性,实际业务中就要在每个方法写逻辑,根据你当前要构建什么类,

//去相应设置对象的各个属性。

//比如,该类构建的是一个女人,所以我把对象里的属性都设置与女人有关,

//然后set到对象,最后通过createPeople 方法返回我构建的对象。

void buildHead() {
       people.setHead("女人的头");
   }

   void buildBody() {
       people.setBody("女人的身体");
   }

   void buildHand() {
       people.setHand("女人的手");
   }

   void buildFoot() {
       people.setFoot("女人的脚");
   }

   People createPeople() {
       return people;
   }

}

指挥者(Director)

public class Director {
   private Builder builder;

   public Director(Builder builder) {
       this.builder = builder;
   }

   public People construct() {
       builder.buildBody();
       builder.buildFoot();
       builder.buildHand();
       builder.buildHead();
       return builder.createPeople();
   }
/**
* 放开下面的注释,使用测试类中注释的代码。
*/
//    public Director() {
//
//    }
//
//    public People construct(Builder builder) {
//        builder.buildBody();
//        builder.buildFoot();
//        builder.buildHand();
//        builder.buildHead();
//        return builder.createPeople();
//    }

下面是 client 调用的方式

public class ClientTest {
   public static void main(String[] args) {

/**
* 与设计者类同理,两种方法,注释与非注释方法任选
*/
//        Director director = new Director();
//        People people = director.construct(new ManBuilder());
//        System.out.println(people.toString());
       Director director = new Director(new ManBuilder());
       People people = director.construct();

       System.out.println(people.toString());
   }

}

输出结果

下面是我代码结构图,需要的请加微信

总结:

使用建造者模式可以使客户端不必知道产品内部组成的细节。易于扩展具体建造者,并且具体建造者 之间没有依赖关系。但是缺点很明显,所有的具体建造者 都要用相同的 产品属性,要共用一个模型,想打破这一局面可以用工厂方法,或者使用抽象工厂,大家有没有发现工厂模式与建造者有些共性呢。

作者:

喜欢围棋和编程。

 
发布于 分类 编程标签

发表评论

电子邮件地址不会被公开。