设计模式之建造模式

建造模式是对象的创建模式。建造模式可以将产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。

一个例子

上古时期女娲造人,首先要新建一个人的类,但是女娲不只可以造人,它可以创造万物,所以,这里定义一个标识接口叫Product(产品)

public interface Product {
}
public class Man implements Product{
	private String soul;//灵魂
	private String earsAndEyes;//耳目
	private String arm;//手臂
	//。。。省略其他属性
	public String getSoul() {
		return soul;
	}
	public void setSoul(String soul) {
		this.soul = soul;
	}
	public String getEarsAndEyes() {
		return earsAndEyes;
	}
	public void setEarsAndEyes(String earsAndEyes) {
		this.earsAndEyes = earsAndEyes;
	}
	public String getArm() {
		return arm;
	}
	public void setArm(String arm) {
		this.arm = arm;
	}
}

那么想要造人需要有一定的标准和步骤,这里定义一个接口来规范创造的步骤(抽象的建造者):

public interface Builder {
	//建造方法1
	void buildPart1();
	//建造方法2
	void buildPart2();
	//建造方法3
	void buildPart3();
	//返回产品的方法
	Product productResult();
}

创造人的步骤是buildPart1》buildPart2》buildPart3,最后的方法是返回创造的这个人
具体的建造者

public class ManBuilder implements Builder {
	private Man man = new Man();
	@Override
	public void buildPart1() {
		man.setArm("男人--》生手臂");
	}
	@Override
	public void buildPart2() {
		man.setEarsAndEyes("男人--》生耳目");
	}
	@Override
	public void buildPart3() {
		man.setSoul("男人--》生灵魂");
	}
	@Override
	public Man productResult() {
		return man;
	}
}

在创造人的过程中,冥冥之中有一个指挥者,指挥者委托女娲造人

public class Director {
	public Man makeMan(Builder builder){
		builder.buildPart1();
		builder.buildPart2();
		builder.buildPart3();
		return (Man) builder.productResult();
	}
}

测试代码

		Director director = new Director();//客户端只需要跟指挥者打交道
		Man man =director.makeMan(new ManBuilder());
		System.out.println(man.getArm());
		System.out.println(man.getEarsAndEyes());
		System.out.println(man.getSoul());

上边例子中只有一个产品类,对应的也只有一个具体的建造者类。如果有两个产品的话,就应当有两个具体的建造者类,女娲造人之后感觉人类很孤单,决定造点动物玩玩:

public class Dog implements Product{
	private String leg;
	private String head;
	public String getLeg() {
		return leg;
	}
	public void setLeg(String leg) {
		this.leg = leg;
	}
	public String getHead() {
		return head;
	}
	public void setHead(String head) {
		this.head = head;
	}
}

dog的具体建造者:

public class DogBuilder implements Builder {
	private Dog dog = new Dog();
	@Override
	public void buildPart1() {
		dog.setLeg("狗--》生腿");
	}
	@Override
	public void buildPart2() {
		dog.setHead("狗--》生头");
	}
	@Override
	public void buildPart3() {
	}
	@Override
	public Dog productResult() {
		return dog;
	}
}

指挥者类相应的增加一个方法(makeDog):

public class Director {
	public Man makeMan(Builder builder){
		builder.buildPart1();
		builder.buildPart2();
		builder.buildPart3();
		return (Man) builder.productResult();
	}
	public Dog makeDog(Builder builder){
		builder.buildPart1();
		builder.buildPart2();
		builder.buildPart3();
		return (Dog) builder.productResult();
	}
}

测试:

Director director = new Director();
		Man man =director.makeMan(new ManBuilder());
		Dog dog =director.makeDog(new DogBuilder());
		System.out.println(man.getArm());
		System.out.println(man.getEarsAndEyes());
		System.out.println(man.getSoul());
		System.out.println("==============");
		System.out.println(dog.getHead());
		System.out.println(dog.getLeg());

本模式涉及到四个角色:

  • 抽象建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口独立于应用程序的商业逻辑。产品对象有多少零件抽象建造者就应该有多少个建造方法。
  • 具体建造者(ManBuilder)角色:这个角色是与应用程序紧密相关的一些类,此类要完成的任务包括:
    1. 实现抽象建造者接口,实现一步一步创建产品的步骤。
    2. 在建造完成后,提供产品的实例。
  • 指挥者(Director)角色:调用具体建造者角色以创建产品对象。指挥者并没有产品类的具体知识,整整拥有产品类具体知识的是具体的建造者
  • 产品(Man)角色:一般来说,一个系统中会有多于一个的产品类,而且这些类很有可能是不相关联的,所以需要建一个标识接口。

省略抽象建造者、省略指挥者

建造模式在实现时可以根据具体情况做一些变化。
首先,如果设计师确定只需要一个具体建造者角色的话,可以省略掉抽象建造者角色,因为如果只有一个具体建造者,就不需要什么规范了;抽象建造者被省略掉了,还可以在省略掉指挥者:

public class ManBuilder{
	private Man man = new Man();

	public void buildPart1() {
		man.setArm("男人--》生手臂");
	}

	public void buildPart2() {
		man.setEarsAndEyes("男人--》生耳目");
	}

	public void buildPart3() {
		man.setSoul("男人--》生灵魂");
	}

	public Man productResult() {
		return man;
	}
	//建造产品的方法
	public Man makeProduct(){
		buildPart1();
		buildPart2();
		buildPart3();
		return productResult();
	}
}

过渡到模板方法

准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。这就是模板方法模式。
有意思的是,这个特殊的建造模式与模板方法有相似之处,makeProduct就是一个模板方法,模板方法里边包含的就是基本方法。
如果系统的要求发生变化、要求有不同的零件生成逻辑时,那么有两种选择:一是修改这个退化的建造模式,将它改回成为完全的建造模式;二是不修改已有代码,将这个ManBuilder扩展到不同的子类,在这些子类里面置换掉需要改变的建造方法。
第一种选择了建造模式;第二种选择了模板方法模式。

猜你喜欢

转载自blog.csdn.net/administratorJWT/article/details/86582538