设计模式——建造者模式

1 建造者模式

建造者模式,是将一个复杂的对象的 构建 与它的 表示 分离,使得同样的构建过程可以创建不同的表示。创建者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。
复制代码

首先看一个例子

1.盖房项目需求
(1)	需要建房子:这一过程为打桩、砌墙、封顶

(2)	房子有各种各样的,比如普通房,高楼,别墅,各种房子的过程虽然一样,但是要求不要相同的.

(3)	请编写程序,完成需求.
复制代码
2.传统方式解决
//面型接口编程,首先定义一个抽象类
public abstract class AbstractHouse {

	public abstract void buildBasic();//打地基表示过程
	public abstract void buildWalls();//砌墙表示过程
	public abstract void roofed();	//封顶表示过程
	
	//构建过程
	public void build() {
		buildBasic();
		buildWalls();
		roofed();
	}
}

//盖一个普通的房子
public class CommonHouse extends AbstractHouse {

	@Override
	public void buildBasic() {
		System.out.println(" 普通房子打地基 ");
	}

	@Override
	public void buildWalls() {
		System.out.println(" 普通房子砌墙 ");
	}

	@Override
	public void roofed() {
		System.out.println(" 普通房子封顶 ");
	}
}

//盖一个高楼的房子
public class HighBuilding extends AbstractHouse {

	@Override
	public void buildBasic() {
		System.out.println(" 高楼打地基 ");
	}

	@Override
	public void buildWalls() {
		System.out.println(" 高楼砌墙 ");
	}

	@Override
	public void roofed() {
		System.out.println(" 高楼封顶 ");
	}
}

//测试类
public class Test {
	public static void main(String[] args) {
		AbstractHouse commonHouse = new CommonHouse();
		commonHouse.build();
		
		AbstractHouse highBuilding = new HighBuilding();
		highBuilding.build();
	}

}
复制代码
2.传统方式的问题分析

(1) 优点是比较好理解,简单易操作。

(2) 设计的程序结构,过于简单,没有设计缓存层对象,程序的扩展和维护不好. 也就是说,这种设计方案,把产 品(即:房子) 和 创建产品的过程(即:建房子流程) 封装在一起,耦合性增强了。

(3) 解决方案:将产品和产品建造过程解耦 => 建造者模式.

2 建造者模式基本介绍

建造者模式

建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。

建造者模式一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。

角色

Builder(抽象建造者):它为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般声明两类方法,一类方法是buildPartX(),它们用于创建复杂对象的各个部件;另一类方法是getResult(),它们用于返回复杂对象。Builder既可以是抽象类,也可以是接口。

ConcreteBuilder(具体建造者):它实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确它所创建的复杂对象,也可以提供一个方法返回创建好的复杂产品对象。

Product(产品角色):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。

Director(指挥者):指挥者又称为导演类,它负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,可以在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。客户端一般只需要与指挥者进行交互,在客户端确定具体建造者的类型,并实例化具体建造者对象(也可以通过配置文件和反射机制),然后通过指挥者类的构造函数或者Setter方法将该对象传入指挥者类中。

在建造者模式的定义中提到了复杂对象,那么什么是复杂对象?简单来说,复杂对象是指那些包含多个成员属性的对象,这些成员属性也称为部件或零件,如汽车包括方向盘、发动机、轮胎等部件,电子邮件包括发件人、收件人、主题、内容、附件等部件

示例

1.产品角色 House

public class House {
	private String baise;
	private String wall;
	private String roofed;
	// 省略 getter, setter, toString
}
复制代码

2.抽象建造者 HouseBuilder

public abstract class HouseBuilder {

    //在抽象建造者里返回一个构建好的房子
    //也可以在抽象建造者内定义抽象方法,具体的建造者内返回房子
	protected House house = new House();
	
	//将建造的流程写好, 抽象的方法
	public abstract void buildBasic();
	public abstract void buildWalls();
	public abstract void roofed();
	
	//建造房子好, 将产品(房子) 返回
	public House buildHouse() {
		return house;
	}
}
复制代码

3.具体建造者 HighBuilding,CommonHouse

public class HighBuilding extends HouseBuilder {

	@Override
	public void buildBasic() {
		System.out.println(" 高楼的打地基100米 ");
	}

	@Override
	public void buildWalls() {
		System.out.println(" 高楼的砌墙20cm ");
	}

	@Override
	public void roofed() {
		System.out.println(" 高楼的透明屋顶 ");
	}
}


public class CommonHouse extends HouseBuilder {

	@Override
	public void buildBasic() {
		System.out.println(" 普通房子打地基5米 ");
	}

	@Override
	public void buildWalls() {
		System.out.println(" 普通房子砌墙10cm ");
	}

	@Override
	public void roofed() {
		System.out.println(" 普通房子屋顶 ");
	}
}    
复制代码

4.指挥者 HouseDirector,指挥构建过程

//指挥者,这里去指定制作流程,返回产品
public class HouseDirector {
	
	HouseBuilder houseBuilder = null;

	//构造器传入 houseBuilder
	public HouseDirector(HouseBuilder houseBuilder) {
		this.houseBuilder = houseBuilder;
	}

	//通过setter 传入 houseBuilder
	public void setHouseBuilder(HouseBuilder houseBuilder){
		this.houseBuilder = houseBuilder;
	}
	
	//如何处理建造房子的流程,交给指挥者
	public House constructHouse() {
		houseBuilder.buildBasic();
		houseBuilder.buildWalls();
		houseBuilder.roofed();
		return houseBuilder.buildHouse();
	}
}
复制代码

5.客户端测试

public class Test {
	public static void main(String[] args) {
		
		//盖普通房子
		CommonHouse commonHouse = new CommonHouse();
		//准备创建房子的指挥者
		HouseDirector houseDirector = new HouseDirector(commonHouse);
		
		//完成盖房子,返回产品(普通房子)
		House house = houseDirector.constructHouse();
		
		//System.out.println("输出流程");
		
		System.out.println("--------------------------");
		//盖高楼
		HighBuilding highBuilding = new HighBuilding();
		//重置建造者
		houseDirector.setHouseBuilder(highBuilding);
		//完成盖房子,返回产品(高楼)
		houseDirector.constructHouse();
	}
}
复制代码

附:可以通过反射机制和配置文件配合,创建具体建造者对象

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        
        HouseDirector houseDirector = new HouseDirector();
    
        // 从数据库或者配置文件中读取具体建造者类名
        Class c = Class.forName("com.designpattern.CommonHouse");
        
        CommonHouse commonHouse = (CommonHouse) c.newInstance();
        House commonHouser = houseDirector.setHouseBuilder(commonHouse);
        System.out.println(commonHouse.toString());
    }
}
复制代码

3 建造者模式的注意事项和细节

优点:

1、使用建造者模式可以使客户端不必知道产品内部组成的细节。

2、具体的建造者类之间是相互独立的,这有利于系统的扩展。

3、具体的建造者相互独立,因此可以对建造的过程逐步细化,而不会对其他模块产生任何影响。
 
4、可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰, 也更方便使用程序来控制创建过程。

5、增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合 “开闭 原则”。
复制代码

缺点:

1、 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使 用建造者模式,因此其使用范围受到一定的限制。

2、如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,因 此在这种情况下,要考虑是否选择建造者模式。
复制代码

抽象工厂模式 VS 建造者模式

与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族 。

在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,
而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象 。

如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车
复制代码

4 建造者模式在 JDK 的应用和源码分析

待补
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享