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

news2024/11/25 16:44:48

一、建造者模式概述

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

  • 建造者模式分析
    • 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)
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)
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");
	}

}
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)
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)
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)
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 version="1.0"?>
<config>
	<className>builder.livingdecorator.ConcreteDecorator1</className>
</config>
        2.7 main方法实现建造者模式
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图

三、代码结构图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1604669.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TCP/IP 协议栈在 Linux 内核中的 运行时序分析

1、Linux内核概述 1.1 Linux内核结构 一个完整的Linux内核一般由5部分组成&#xff0c;它们分别是内存管理、进程管理、进程间通信、bai虚拟文件系统和网络接口。 1、内存管理 内存管理主要完成的是如何合理有效地管理整个系统的物理内存&#xff0c;同时快速响应内核各个子…

SQL Serve---嵌套查询

定义 嵌套查询&#xff1a;主要用于复杂的查询中。在SQL语言中&#xff0c;一个Select From Where语句称为一个查询块&#xff0c;将一个查询块嵌套在另一个查询的Where子句或Having短语中的查询称为嵌套查询。 子查询的类型 使用别名的子查询 使用IN和NOT IN的子查询 使用比较…

Modelsim自动化仿真脚本(TCL)——简单实例

目录 1. Modelsim与TCL脚本的关系 2.实验文件 2.1设计文件 2.2仿真测试文件 2.3. 脚本文件 3. 实验步骤 3.1. 创建文件夹 3.2. 指定路径 3.3. 创建工程 3.4. 运行命令 3.4. 实验效果 1. Modelsim与TCL脚本的关系 TCL&#xff08;Tool Command Language&#xff09;是…

基于机器学习的人脸发型推荐算法研究与应用实现

1.摘要 本文主要研究内容是开发一种发型推荐系统&#xff0c;旨在识别用户的面部形状&#xff0c;并根据此形状推荐最适合的发型。首先&#xff0c;收集具有各种面部形状的用户照片&#xff0c;并标记它们的脸型&#xff0c;如长形、圆形、椭圆形、心形或方形。接着构建一个面部…

我到底应该先学python还是C++?

根据你的情况&#xff0c;我还是建议你继续用Python&#xff0c;因为中学阶段最应该死磕的是算法。 也不需要精通Python&#xff0c;因为编程语言只是工具&#xff0c;能够熟练使用就可以了&#xff0c;而且现在信息学竞赛几乎都已经支持Python了&#xff0c;C已经不是必选项了…

宿舍预付费电控系统

1.系统概述 宿舍预付费电控系统是一种现代化的电力管理解决方案&#xff0c;旨在提高校园或公寓楼的能源效率&#xff0c;同时确保公平、透明的用电管理。通过预付费模式&#xff0c;用户需先充值后用电&#xff0c;避免了后期收费的困扰&#xff0c;也鼓励了节能行为。 2.功…

LangChain LangServe 学习笔记

LangChain LangServe 学习笔记 0. 引言1. LangServe 概述2. 特性3. 限制4. 安装5. 示例应用程序6. OpenAPI文档7. Python SDK 客户端8. Playground9. 聊天可运行页面 0. 引言 使用 LangServe 可以立即将您的LLM应用程序变成 API 服务器。 LangServe 使用 FastAPI 构建&#x…

道合顺传感新品上市!高性能氢气传感器DSB14-G3K-J详解

道合顺传感高性能氢气传感器DSB14-G3K-J正式发布&#xff01;超强抗干扰能力优势明显。应对氢气安全挑战、高性能氢气传感器国产化、为储能保驾护航。 氢气&#xff0c;作为现今能源领域中的新贵&#xff0c;在储能行业中应用广泛且备受瞩目。但氢气易燃、易爆特性使其在生产、…

鉴权设计(一)———— 登录验证

1、概述 网站系统出于安全性的考虑会对用户进行两个层面的校验&#xff1a;身份认证以及权限认证。这两个认证可以保证只有特定的用户才能访问特定的数据的需求。 本文先实现一个基于jwt拦截器redis注解实现的简单登录验证功能。 2、设计思路 jwt用于签发token。 拦截器用于拦…

PDF被加密无法打印的解决办法

思路很清晰&#xff1a;先解密→再打印 分享四个工具&#xff0c;可以轻松解密PDF&#xff1a; ⭐i love pdf I LOVE PDF是一款免费的PDF网站&#xff0c;界面设计简洁&#xff0c;首页没有广告&#xff0c;但每个功能的操作界面是有广告的&#xff0c;不会影响使用。 部分功…

MAC M1版IDEA热部署JRebel

1、在idea里面安装jrebel插件 2、下载激活工具&#xff1a;ReverseProxy_darwin_amd64 下载地址&#xff08;Mac早期用户使用Safari下载&#xff0c;不要用Chrome&#xff0c;否则下载之后会把.dms后缀名去掉&#xff09; 特别注意&#xff1a;M1用户请使用下面的下载&#xff…

ORA-19760: error starting change tracking(btc)

备份时候显示ORA19760 1、使用命令查看参数是否开启 SELECT * FROM v$block_change_tracking;2、未开启状态 3、查询数据文件位置 select * from v$dbfile&#xff1b;路径截止到最后/前面。 4、开启块修改跟踪 alter database enable block change tracking using file …

市场份额第一!博睿数据持续领跑中国APM市场

近日&#xff0c;全球领先的IT市场研究和咨询公司IDC发布《中国IT统一运维软件产品市场跟踪报告&#xff0c;2023H2》。报告显示&#xff0c;2023下半年博睿数据以 17.6%的市场份额蝉联 APM(应用性能监控)市场第一。2023年全年博睿数据以18.8%的市场份额持续领跑中国APM市场。 …

从三大层次学习企业架构框架TOGAF

目录 前言 掌握TOGAF的三个层次 层次1&#xff1a;怎么学&#xff1f; 层次2&#xff1a;怎么用&#xff1f; 层次3&#xff1a;怎么思&#xff1f; 结束语 前言 对于一名架构师来讲&#xff0c;如果说编程语言是知识库层次中的入门石&#xff0c;那么企业架构框架则相当…

基于springboot实现房屋租赁管理系统设计项目【项目源码+论文说明】计算机毕业设计

基于springboot实现房屋租赁管理系统设计演示 摘要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对房屋租赁信息管理混乱&…

【面试经典 150 | 链表】删除链表的倒数第 N 个结点

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;统计节点个数方法二&#xff1a;双指针 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本…

官方助力:SpringAI快速尝鲜体验(SpringBoot3+Gradle8+JDK17)

SpringAI 自从OpenAI的ChatGPT爆火之后&#xff0c;各种AI大模型开始席卷互联网&#xff0c;作为知名框架的Spring官方也是小小的顺应了一波潮流&#xff0c;就在不久前官方推出了针对AI的部分&#xff0c;称为SpringAI目前最新版本为0.8.1,下面是官网的截图。 直通车https:/…

第十二章 屏幕后处理效果

屏幕后处理效果是实现屏幕特效的常见方法。 建立一个基本的屏幕后处理的脚本 屏幕后处理指的是在渲染完整个场景得到屏幕图像后,再对这个图像进行一系列操作,实现各种屏幕特效。 想要实现屏幕后处理的基础在于抓取屏幕。Unity为我们提供了一个接口-OnRenderImage函数。 声…

学习笔记<2024.4.15-2024.4.21>:Attention Is All You Need

Transformer中Self-Attention以及Multi-Head Attention详解 (https://www.bilibili.com/video/BV15v411W78M/?spm_id_from333.337.search-card.all.click&vd_sourcef32decb03075b4a1833fe5c47c11ba94)

什么是CPU与GPU,它们之间有什么关系

什么是CPU与GPU&#xff0c;它们之间有什么关系一、CPU1. 核心功能2. 工作原理3. 组成部分4. 发展历程5. 性能指标6. 架构种类7. 发展趋势8. 应用领域 二、GPU三、CPU与GPU的关系 什么是CPU与GPU&#xff0c;它们之间有什么关系 一、CPU CPU&#xff0c;全称是“Central Proc…