建造者模式
-
定义
指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。 -
优点
1.封装性好,构建和表示分离。
2.扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
3.客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。 -
缺点
1.产品的组成部分必须相同,这限制了其使用范围。
2.如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式
角色要素
建造者(Builder)模式由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成
Product: 最终要生成的对象,例如 Computer实例。
Builder: 构建者的抽象基类(有时会使用接口代替)。其定义了构建Product的抽象步骤,其实体类需要实现这些步骤。其会包含一个用来返回最终产品的方法Product getProduct()。
ConcreteBuilder: Builder的实现类。
Director: 决定如何构建最终产品的算法. 其会包含一个负责组装的方法void Construct(Builder builder), 在这个方法中通过调用builder的方法,就可以设置builder,等设置完成后,就可以通过builder的 getProduct() 方法获得最终的产品。
实现
一个房子里有椅子,电视,和桌子,有抽象的工人可以造这三个产品,不同的工人创造出不同的产品,指导者可以指定要那个工人创建指定的产品,指导者指定建造细节(construct),可以只造椅子不造桌子等等需求都可以满足,完工后 工人交付房子
public class builder {
class House{
String chair;
String TV;
String desk;
public String getChair() {
return chair;
}
public void setChair(String chair) {
this.chair = chair;
}
public String getTV() {
return TV;
}
public void setTV(String TV) {
this.TV = TV;
}
public String getDesk() {
return desk;
}
public void setDesk(String desk) {
this.desk = desk;
}
@Override
public String toString() {
return "House{" +
"chair='" + chair + '\'' +
", TV='" + TV + '\'' +
", desk='" + desk + '\'' +
'}';
}
}
abstract class AbstractWorker{
public abstract void buildChair();
public abstract void buildTV();
public abstract void buildDesk();
public abstract House getHouse();
}
/**
* worker1可以建造红木的家具
*/
class worker1 extends AbstractWorker{
protected House house = new House();
@Override
public void buildChair() {
house.setChair("红木椅子");
System.out.println("work1建造红木椅子");
}
@Override
public void buildTV() {
house.setTV("红木牌电视");
System.out.println("work1建造红木牌电视");
}
@Override
public void buildDesk() {
house.setDesk("红木桌子");
System.out.println("work1建造红木桌子");
}
@Override
public House getHouse() {
return house;
}
}
/**
* worker2可以建造檀木的家具
*/
class worker2 extends AbstractWorker{
protected House house = new House();
@Override
public void buildChair() {
house.setChair("檀木椅子");
System.out.println("work2建造檀木椅子");
}
@Override
public void buildTV() {
house.setTV("檀木牌电视");
System.out.println("work2建造檀木牌电视");
}
@Override
public void buildDesk() {
house.setDesk("檀木桌子");
System.out.println("work2建造檀木桌子");
}
@Override
public House getHouse() {
return house;
}
}
/**
* 监工角色
*/
class Direct{
private AbstractWorker worker;
public AbstractWorker getWorker() {
return worker;
}
public void setWorker(AbstractWorker worker) {
this.worker = worker;
}
public void construct(){
worker.buildChair();
worker.buildTV();
worker.buildDesk();
}
}
@Test
public void test(){
//监控者来控制具体想要建造那种家具
Direct direct = new Direct();
AbstractWorker worker1 = new worker1();
direct.setWorker(worker1);
direct.construct();
House house1 = worker1.getHouse();
System.out.println(house1);
System.out.println("--------------------------------");
AbstractWorker worker2 = new worker2();
direct.setWorker(worker2);
direct.construct();
House house = worker2.getHouse();
System.out.println(house);
}
}
另一种使用场景
当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。
直接方便进行链式编程
public class Person {
//必须
private String name;
//必须
private String age;
//非必须
private String sex;
//非必须
private String company;
public Person(Builder builder){
this.name = builder.name;
this.age = builder.age;
this.sex = builder.sex;
this.company = builder.company;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
", sex='" + sex + '\'' +
", company='" + company + '\'' +
'}';
}
public static class Builder{
private String name;
private String age;
private String sex;
private String company;
public String getName() {
return name;
}
public Builder setName(String name) {
this.name = name;
return this;
}
public String getAge() {
return age;
}
public Builder setAge(String age) {
this.age = age;
return this;
}
public String getSex() {
return sex;
}
public Builder setSex(String sex) {
this.sex = sex;
return this;
}
public String getCompany() {
return company;
}
public Builder setCompany(String company) {
this.company = company;
return this;
}
public Person build(){
return new Person(this);
}
}
public static void main(String[] args) {
Person person = new Person.Builder()
.setName("黄硕")
.setAge("18")
.setSex("男")
.setCompany("jld").build();
System.out.println(person);
}
}