【创建型模式】建造者模式

一、建造者模式概述

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

  • 建造者模式分析
    • 1.将客户端与包含多个部件得复杂对象得创建过程分离,客户端无需知道复杂对象得内部组成部分与装配方式,只需要知道所需建造者得类型即可;
    • 2.关注如何逐步创建一个复杂得对象,不同得建造者定义了不同得创建过程。
  • 建造者模式的优缺点
    • 优点
      • 1.客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象;
        • 2.每一个具体建造者都相对独立,与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,扩展方便,符合开闭原则;
      • 3.可以更加精细地控制产品的创建过程。
    • 缺点
      • 1.建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,不适合使用建造者模式,因此其使用范围受到一定的限制;
      • 2.如果产品的内部变化复杂,可能会需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加了系统的理解难度和运行成本
  • 适用环境:
    • 1.需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员变量;
    • 2.需要生成的产品对象的属性相互依赖,需要指定其生成顺序;
    • 3.对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中;
    • 4.隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

二、代码实现

建造者模式包含四个角色:

  • 抽象建造者: 创建一个Product 对象的各个部件指定的接口/抽象类;
  • 具体建造者: 实现接口,构建和装配各个部件;
  • **产品:**一个具体的产品对象;
  • 指挥者: 构建一个使用Builder 接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用:
    • 1.隔离了客户与对象的生产过程;
    • 2.负责控制产品对象的生产过程。

其中,对于指挥者类有一些深入讨论

  • 1 省略Director:将construct()方法中的参数去掉,直接在construct()方法中调用buildPartX()方法;
  • 2 钩子方法的引入:钩子方法(Hook Method):返回类型通常为boolean类型,方法名一般为isXXX()。
2.1 抽象建造者(Decorator)
java 复制代码
package builder.livingdecorator;
//抽象建造者
public 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;
	}

}
2.2 具体建造者(ConcreteDecorator1、ConcreteDecorator2)
java 复制代码
package builder.livingdecorator;
//具体建造者:具体装修工人1
public class ConcreteDecorator1 extends Decorator {

	@Override
	public void buildWall() {
		// TODO Auto-generated method stub
		product.setWall("w1");
	}

	@Override
	public void buildTV() {
		// TODO Auto-generated method stub
		product.setTV("TV1");
	}

	@Override
	public void buildSofa() {
		// TODO Auto-generated method stub
		product.setSofa("sf1");
	}

}
java 复制代码
package builder.livingdecorator;
//具体建造者:具体装修工人2
public class ConcreteDecorator2 extends Decorator {
	
	@Override
	public void buildWall() {
		// TODO Auto-generated method stub
		product.setWall("w2");
	}

	@Override
	public void buildTV() {
		// TODO Auto-generated method stub
		product.setTV("TV2");
	}

	@Override
	public void buildSofa() {
		// TODO Auto-generated method stub
		product.setSofa("sf2");
	}
}
2.3 产品(Parlour)
java 复制代码
package builder.livingdecorator;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

//产品:客厅
public 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() {
		JFrame jf = new JFrame("建造者模式测试");
		Container contentPane = jf.getContentPane();
		JPanel p = new JPanel();
		JScrollPane sp = new JScrollPane(p);
		String parlour = wall + TV + sofa;
		String picture = "src/builder/livingdecorator/" + parlour + ".jpg";
		//String picture = "src/structural_patterns/builder/decorator/" +name ;
		JLabel l = new JLabel(new ImageIcon(picture));
		p.setLayout(new GridLayout(1, 1));
		p.setBorder(BorderFactory.createTitledBorder("客厅"));
		p.add(l);
		contentPane.add(sp, BorderLayout.CENTER);
		jf.pack();
		jf.setVisible(true);
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
}
2.4 指挥者(ProjectManager)
java 复制代码
package builder.livingdecorator;

//指挥者:项目经理
public	class ProjectManager {
	private Decorator builder;
	public ProjectManager(Decorator builder) {
		this.builder = builder;
	}
		// 产品构建与组装方法
	public Parlour decorate() {
		builder.buildWall();
		builder.buildTV();
		builder.buildSofa();
		return builder.getResult();
	}
}
2.5 实例化工具代码(ReadXML)
java 复制代码
package builder.livingdecorator;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
public class ReadXML
{
    public static Object getObject()
    {
        try
        {
            DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();
            DocumentBuilder builder=dFactory.newDocumentBuilder();
            Document doc;                           
            doc=builder.parse(new File("src/builder/livingdecorator/config.xml"));
            NodeList nl=doc.getElementsByTagName("className");
            Node classNode=nl.item(0).getFirstChild();
            String cName=classNode.getNodeValue();
            System.out.println("新类名:"+cName);
            Class<?> c=Class.forName(cName);
              Object obj=c.newInstance();
            return obj;
         }  
         catch(Exception e)
         {
                   e.printStackTrace();
                   return null;
         }
    }
}
2.6 配置文件(config.xml)
XML 复制代码
<?xml version="1.0"?>
<config>
	<className>builder.livingdecorator.ConcreteDecorator1</className>
</config>
2.7 main方法实现建造者模式
java 复制代码
package builder.livingdecorator;

import java.awt.*;
import javax.swing.*;

public class ParlourDecoratorClient {
	public static void main(String[] args) {
		try {
            //Decorator d=new ConcreteDecorator2();
			Decorator d=(Decorator) ReadXML.getObject();
            ProjectManager m=new ProjectManager(d);
            Parlour p=m.decorate();
            p.show();
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
	}
}
2.8 UML图

三、代码结构图

相关推荐
morris1313 分钟前
【SpringBoot】Xss的常见攻击方式与防御手段
java·spring boot·xss·csp
七星静香28 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
Jacob程序员29 分钟前
java导出word文件(手绘)
java·开发语言·word
ZHOUPUYU30 分钟前
IntelliJ IDEA超详细下载安装教程(附安装包)
java·ide·intellij-idea
stewie633 分钟前
在IDEA中使用Git
java·git
Elaine2023911 小时前
06 网络编程基础
java·网络
G丶AEOM1 小时前
分布式——BASE理论
java·分布式·八股
落落鱼20131 小时前
tp接口 入口文件 500 错误原因
java·开发语言
想要打 Acm 的小周同学呀1 小时前
LRU缓存算法
java·算法·缓存
镰刀出海1 小时前
Recyclerview缓存原理
java·开发语言·缓存·recyclerview·android面试