软件设计模式--第二章 创建型模式--建造者模式


第二章 创建型模式

1、创建型模式概述

  • 主要特点
    对象的创建与使用分离”,这样可以降低系统的耦合度。

  • 创建型模式分为以下几种:
    单例(Singleton)模式 :某个类只能生成一个实例,该类提供了一个全 局访问点供外部获取该实例,其拓展是有限多例模式。
    原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克 隆出多个和原型类似的新实例。
    工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子 类决定生产什么产品。
    抽象工厂(Abstract Factory)模式:提供一个创建产品族的接口,其每 个子类可以生产一系列相关的产品。
    建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分, 然后根据不同需要分别创建它们,最后构建成该复杂对象。

2、建造者模式

(1)模式的定义与特点

  1. 定义:指将一个复杂对象的构造与它的表示分离,使同样的构建 过程可以创建不同的表示,它是 将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。

  2. 优点:
    1)各个具体的建造者相互独立的,有利于系统的扩展
    2)客户端不必知道产品内部组成的细节,便于控制细节 风险。

  3. 缺点:
    1)产品的组成部分必须相同,**这限制了其使用范围;
    2)如果产品的内部变化复杂,该模式会增加很多的建造 者类

建造者模式注重零部件的组装过程,工厂模式更注重零部件的创建过程

(2)模式的结构与实现

1、结构

  • 产品角色(Product):它是包含多个组成部件的复杂对象, 由具体建造者来创建其各个组成部件。
  • 抽象建造者(Builder):是一个包含创建产品各个子部件的 抽象方法的接口,它通常还包含一个返回复杂产品的方法 getResult()。
  • 具体建造者(ConcreteBuilder):实现了Builder接口,完 成复杂产品的各个部件的具体创建方法。
  • 指挥者(Director):它调用建造者对象中的部件构造与装 配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

结构图:
在这里插入图片描述

原理图:
在这里插入图片描述

代码:
1)产品角色:是包含多个组成部件的复杂对象。

class Product { 
	private String partA;
	private String partB;
	private String partC;
 }
public void setPartA(String partA) {
	this.partA = partA;  }

public void setPartB(String partB) { 
	this.partB = partB;
}
public void setPartC(String partC) {
	this.partC = partC;
  }

public void show(){
 //显示产品的特性
		}
}

2)抽象建造者:包含创建产品各个子部件的抽象方法。

abstract class Builder {
	//创建产品对象
	protected Product product=new Product();
	public abstract void buildPartA();
	public abstract void buildPartB();
	public abstract void buildPartC();
	
	//返回产品对象
	public Product getResult() {
	return product;
	}
}

3)具体建造者:实现了抽象建造者接口。


public class ConcreteBuilder extends Builder {
	public void buildPartA(){
	product.setPartA("建造PartA");
	}
	public void buildPartB(){
	product.setPartA("建造PartB");
	}
	public void buildPartC(){
	product.setPartA("建造PartC");
	}
}

4)指挥者:调用建造者中的方法完成复杂对象的创建。

class Director {
	private Builder builder;
	public Director(Builder builder) {
	this.builder=builder; 
	}
	//产品构建与组装方法
	public Product construct() { 
	builder.buildPartA(); 
	builder.buildPartB(); 
	builder.buildPartC();
	return builder.getResult();
} }

5)客户类

public class Client{
	public static void main(String[] args) {
	// 创建建造者
	Builder builder = new ConcreteBuilder();
	// 创建指挥者,指挥建造者
	Director director = new Director(builder);
	// 通过指挥者完成产品的组装
	Product product = director.construct();
	product.show();
	}
}

2、实现

  • 用建造者模式描 述客厅装修。

类图:
在这里插入图片描述

在这里插入图片描述
代码实现:

产品:客厅

class Parlour {
	private String wall; //墙
	private String TV;   //电视
	private String sofa; //沙发   
	
	public void setWall(String wall) {
	    this.wall = wall;
	}
	public void setTV(String TV) {
	    this.TV = TV;
	}
	public void setSofa(String sofa) {
	    this.sofa = sofa;
	}	
	public void show()
	{
		System.out.println("客厅装修展示");
	}
		
}

抽象建造者:装修工人

abstract class Decorator {
	  //创建产品对象
	  protected  Parlour product=new Parlour();
	  // 创建子部件的方法
	  public  abstract void buildWall();
	  public  abstract void buildTV();
	  public  abstract void buildSofa();
	  //返回产品对象
	  public  Parlour getResult() {
	         return  product;
	  }
}

具体建造者:具体装修工人1

class ConcreteDecorator1  extends Decorator{
	public void buildWall() {
		product.setWall("w1");
	}
	public void buildTV() {
		product.setTV("TV1");
	}
	public void buildSofa() {
		product.setSofa("sf1");
	}
}

具体建造者:具体装修工人2

class ConcreteDecorator2  extends Decorator{
	public void buildWall() {
		product.setWall("w2");
	  }
	  public void buildTV() {
		  product.setTV("TV2");
	  }
	  public void buildSofa() {
		  product.setSofa("sf2");
	  }
}

指挥者:项目经理

class ProjectManager {
	private Decorator builder;
	
  	public ProjectManager(Decorator builder) {
  	this.builder=builder;
 	 }
 	 
  //产品构建与组装方法
  public Parlour decorate() {
		builder.buildWall();
		builder.buildTV();
		builder.buildSofa();
     	return builder.getResult();
  }
}

confg.xml

<?xml version="1.0" encoding="UTF-8"?>
<config>
	// 具体装修师2
	<className>ConcreteDecorator2</className>
</config>

ReadXML:该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象

class ReadXML{
    //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
    public static Object getObject() {
        try {
            //创建文档对象
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            // 对读取配置文件路径
            doc = builder.parse(new File("src/chapter03/factoryMethod/config.xml"));
            //获取包含类名的文本节点
            NodeList nl = doc.getElementsByTagName("className");  
            Node classNode = nl.item(0).getFirstChild();  // classNode =CattleFarm
            String cName = "chapter03.factoryMethod." + classNode.getNodeValue();
            // cName : chapter03.factoryMethod.CattleFarm
           
            //通过类名生成实例对象并将其返回
            Class<?> c = Class.forName(cName);
            Object obj = c.newInstance();
            return obj;  // return new CattleFarm();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

测试类:

public class ParlourDecorator {
	public static void main(String[] args) {
		try
        {
        	// 抽象建造者:装修工人
			Decorator d;
			// 获取配置文件中的具体建造者:具体装修工人
        	d=(Decorator) ReadXML.getObject();
        	// 创建指挥者
        	ProjectManager m = new ProjectManager(d);  
        	// 通过指挥者完成产品的组装     
            Parlour p = m.decorate();
        	p.show();
        }
        catch(Exception e)
        {
        	System.out.println(e.getMessage());
        }
	}
}

(3)应用场景

建造者模式创建的是复杂对象,其产品的各个部分经常面临着剧烈的变化,但将它们组合在一起的算法却相对稳定.

  • 创建的对象较复杂,由多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的。

  • 产品的构建过程和最终的表示是独立的。

(4)扩展

建造者模式在应用过程中可以根据需要改变,如果创建的产品种类只有一种,只需要一个具体的建造者,这时可以省略掉抽象建造者,甚至可以省略掉指导者角色

  • 可以没有抽象建造者
  • 可以没有指导者
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绿箭柠檬茶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值