设计模式-Builder
程序员文章站
2022-07-06 11:47:00
...
建造者模式: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
提供一种“封装机制”来隔离“复杂对象的各个部”的变化,从而保持系统中的“稳定构建算法”而不随需求的变化而变化。
解决的问题:
主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
使用场景:
1、需要生成的对象具有复杂的内部结构。
2、需要生成的对象内部属性本身相互依赖。
基于这两个要求,Builder或者ConcreteBuilder角色里可以做参数格式以及属性依赖的验证。
与抽象工厂的区别:
用意的区别:建造者模式更加关注与零件装配的顺序;工厂模式专注于产品的生产,而建造者模式专注于相同产品的不同表示形式上。
结构的区别:
1、在建造者模式里,有个指导者,由指导者来管理建造者,用户是与指导者联系的,
2、指导者联系建造者最后得到产品。即建造模式可以强制实行一种分步骤进行的建造过程。
角色:
1、Builder:为创建一个产品对象的各个部件指定抽象接口。
2、ConcreteBuilder:实现抽象类的所有未实现的方法,具体来说一般是两项任务:组建产品;返回组建好的产品。
3、Director:构造一个使用Builder接口的对象。负责调用适当的建造者来组建产品,导演类一般不与产品类发生依赖关系,与导演类直接交互的是建造者类。一般来说,导演类被用来封装程序中易变的部分。
4、Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
Director知道“要做什么”, Builder负责“做出来”;
类图结构:
JDK中的使用案例(基本上是简化的变种):
java.lang.StringBuilder#append()
java.lang.StringBuffer#append()
java.sql.PreparedStatement
举例:
产品类
抽象建造者:
具体建造者:
导演类:
客户端:
-----------------------------------------------------------------------------
在实际的应用中,更常使用的场景是:
Builder 和 ConcreteBuilder 角色合并为一个类
Director类:由Client 来代替
比如:
客户端为:
参考:
http://www.cnblogs.com/beyondbycyx/p/4424579.html
提供一种“封装机制”来隔离“复杂对象的各个部”的变化,从而保持系统中的“稳定构建算法”而不随需求的变化而变化。
解决的问题:
主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
使用场景:
1、需要生成的对象具有复杂的内部结构。
2、需要生成的对象内部属性本身相互依赖。
基于这两个要求,Builder或者ConcreteBuilder角色里可以做参数格式以及属性依赖的验证。
与抽象工厂的区别:
用意的区别:建造者模式更加关注与零件装配的顺序;工厂模式专注于产品的生产,而建造者模式专注于相同产品的不同表示形式上。
结构的区别:
1、在建造者模式里,有个指导者,由指导者来管理建造者,用户是与指导者联系的,
2、指导者联系建造者最后得到产品。即建造模式可以强制实行一种分步骤进行的建造过程。
角色:
1、Builder:为创建一个产品对象的各个部件指定抽象接口。
2、ConcreteBuilder:实现抽象类的所有未实现的方法,具体来说一般是两项任务:组建产品;返回组建好的产品。
3、Director:构造一个使用Builder接口的对象。负责调用适当的建造者来组建产品,导演类一般不与产品类发生依赖关系,与导演类直接交互的是建造者类。一般来说,导演类被用来封装程序中易变的部分。
4、Product:表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
Director知道“要做什么”, Builder负责“做出来”;
类图结构:
JDK中的使用案例(基本上是简化的变种):
java.lang.StringBuilder#append()
java.lang.StringBuffer#append()
java.sql.PreparedStatement
举例:
产品类
public class Product { private String name; private String type; public void showProduct() { System.out.println("名称:" + name); System.out.println("型号:" + type); } public void setName(String name) { this.name = name; } public void setType(String type) { this.type = type; } }
抽象建造者:
public abstract class Builder { public abstract void setPart(String arg1, String arg2); public abstract Product getProduct(); }
具体建造者:
public class ConcreteBuilder extends Builder { private Product product = new Product(); public Product getProduct() { return product; } public void setPart(String name, String type) { product.setName(name); product.setType(type); } }
导演类:
public class Director { private Builder builder = new ConcreteBuilder(); public Product getAProduct() { builder.setPart("宝马汽车", "X7"); return builder.getProduct(); } public Product getBProduct() { builder.setPart("奥迪汽车", "Q5"); return builder.getProduct(); } }
客户端:
public class Client { public static void main(String[] args){ Director director = new Director(); Product product1 = director.getAProduct(); product1.showProduct(); Product product2 = director.getBProduct(); product2.showProduct(); } }
-----------------------------------------------------------------------------
在实际的应用中,更常使用的场景是:
Builder 和 ConcreteBuilder 角色合并为一个类
Director类:由Client 来代替
比如:
public final class Hero { private final Profession profession; private final String name; private final HairType hairType; private final HairColor hairColor; private final Armor armor; private final Weapon weapon; private Hero(Builder builder) { this.profession = builder.profession; this.name = builder.name; this.hairColor = builder.hairColor; this.hairType = builder.hairType; this.weapon = builder.weapon; this.armor = builder.armor; } public Profession getProfession() { return profession; } public String getName() { return name; } public HairType getHairType() { return hairType; } public HairColor getHairColor() { return hairColor; } public Armor getArmor() { return armor; } public Weapon getWeapon() { return weapon; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("This is a ") .append(profession) .append(" named ") .append(name); if (hairColor != null || hairType != null) { sb.append(" with "); if (hairColor != null) { sb.append(hairColor).append(' '); } if (hairType != null) { sb.append(hairType).append(' '); } sb.append(hairType != HairType.BALD ? "hair" : "head"); } if (armor != null) { sb.append(" wearing ").append(armor); } if (weapon != null) { sb.append(" and wielding a ").append(weapon); } sb.append('.'); return sb.toString(); } /** * * The builder class. * */ public static class Builder { private final Profession profession; private final String name; private HairType hairType; private HairColor hairColor; private Armor armor; private Weapon weapon; /** * Constructor */ public Builder(Profession profession, String name) { if (profession == null || name == null) { throw new IllegalArgumentException("profession and name can not be null"); } this.profession = profession; this.name = name; } public Builder withHairType(HairType hairType) { this.hairType = hairType; return this; } public Builder withHairColor(HairColor hairColor) { this.hairColor = hairColor; return this; } public Builder withArmor(Armor armor) { this.armor = armor; return this; } public Builder withWeapon(Weapon weapon) { this.weapon = weapon; return this; } public Hero build() { return new Hero(this); } } }
客户端为:
public class App { public static void main(String[] args) { Hero mage = new Hero.Builder(Profession.MAGE, "Riobard").withHairColor(HairColor.BLACK) .withWeapon(Weapon.DAGGER).build(); System.out.println(mage); } }
参考:
http://www.cnblogs.com/beyondbycyx/p/4424579.html