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


    一、建造者模式概述

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

    • 建造者模式分析
      • 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)
    1. package builder.livingdecorator;
    2. //抽象建造者
    3. public abstract class Decorator {
    4. // 创建产品对象
    5. protected Parlour product = new Parlour();
    6. public abstract void buildWall();
    7. public abstract void buildTV();
    8. public abstract void buildSofa();
    9. // 返回产品对象
    10. public Parlour getResult() {
    11. return product;
    12. }
    13. }
            2.2 具体建造者(ConcreteDecorator1、ConcreteDecorator2)
    1. package builder.livingdecorator;
    2. //具体建造者:具体装修工人1
    3. public class ConcreteDecorator1 extends Decorator {
    4. @Override
    5. public void buildWall() {
    6. // TODO Auto-generated method stub
    7. product.setWall("w1");
    8. }
    9. @Override
    10. public void buildTV() {
    11. // TODO Auto-generated method stub
    12. product.setTV("TV1");
    13. }
    14. @Override
    15. public void buildSofa() {
    16. // TODO Auto-generated method stub
    17. product.setSofa("sf1");
    18. }
    19. }
    1. package builder.livingdecorator;
    2. //具体建造者:具体装修工人2
    3. public class ConcreteDecorator2 extends Decorator {
    4. @Override
    5. public void buildWall() {
    6. // TODO Auto-generated method stub
    7. product.setWall("w2");
    8. }
    9. @Override
    10. public void buildTV() {
    11. // TODO Auto-generated method stub
    12. product.setTV("TV2");
    13. }
    14. @Override
    15. public void buildSofa() {
    16. // TODO Auto-generated method stub
    17. product.setSofa("sf2");
    18. }
    19. }
            2.3 产品(Parlour)
    1. package builder.livingdecorator;
    2. import java.awt.BorderLayout;
    3. import java.awt.Container;
    4. import java.awt.GridLayout;
    5. import javax.swing.BorderFactory;
    6. import javax.swing.ImageIcon;
    7. import javax.swing.JFrame;
    8. import javax.swing.JLabel;
    9. import javax.swing.JPanel;
    10. import javax.swing.JScrollPane;
    11. //产品:客厅
    12. public class Parlour {
    13. private String wall; // 墙
    14. private String TV; // 电视
    15. private String sofa; // 沙发
    16. public void setWall(String wall) {
    17. this.wall = wall;
    18. }
    19. public void setTV(String TV) {
    20. this.TV = TV;
    21. }
    22. public void setSofa(String sofa) {
    23. this.sofa = sofa;
    24. }
    25. public void show() {
    26. JFrame jf = new JFrame("建造者模式测试");
    27. Container contentPane = jf.getContentPane();
    28. JPanel p = new JPanel();
    29. JScrollPane sp = new JScrollPane(p);
    30. String parlour = wall + TV + sofa;
    31. String picture = "src/builder/livingdecorator/" + parlour + ".jpg";
    32. //String picture = "src/structural_patterns/builder/decorator/" +name ;
    33. JLabel l = new JLabel(new ImageIcon(picture));
    34. p.setLayout(new GridLayout(1, 1));
    35. p.setBorder(BorderFactory.createTitledBorder("客厅"));
    36. p.add(l);
    37. contentPane.add(sp, BorderLayout.CENTER);
    38. jf.pack();
    39. jf.setVisible(true);
    40. jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    41. }
    42. }
            2.4 指挥者(ProjectManager)
    1. package builder.livingdecorator;
    2. //指挥者:项目经理
    3. public class ProjectManager {
    4. private Decorator builder;
    5. public ProjectManager(Decorator builder) {
    6. this.builder = builder;
    7. }
    8. // 产品构建与组装方法
    9. public Parlour decorate() {
    10. builder.buildWall();
    11. builder.buildTV();
    12. builder.buildSofa();
    13. return builder.getResult();
    14. }
    15. }
            2.5 实例化工具代码(ReadXML)
    1. package builder.livingdecorator;
    2. import javax.xml.parsers.*;
    3. import org.w3c.dom.*;
    4. import java.io.*;
    5. public class ReadXML
    6. {
    7. public static Object getObject()
    8. {
    9. try
    10. {
    11. DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();
    12. DocumentBuilder builder=dFactory.newDocumentBuilder();
    13. Document doc;
    14. doc=builder.parse(new File("src/builder/livingdecorator/config.xml"));
    15. NodeList nl=doc.getElementsByTagName("className");
    16. Node classNode=nl.item(0).getFirstChild();
    17. String cName=classNode.getNodeValue();
    18. System.out.println("新类名:"+cName);
    19. Class c=Class.forName(cName);
    20. Object obj=c.newInstance();
    21. return obj;
    22. }
    23. catch(Exception e)
    24. {
    25. e.printStackTrace();
    26. return null;
    27. }
    28. }
    29. }
            2.6 配置文件(config.xml)
    1. "1.0"?>
    2. <config>
    3. <className>builder.livingdecorator.ConcreteDecorator1className>
    4. config>
            2.7 main方法实现建造者模式
    1. package builder.livingdecorator;
    2. import java.awt.*;
    3. import javax.swing.*;
    4. public class ParlourDecoratorClient {
    5. public static void main(String[] args) {
    6. try {
    7. //Decorator d=new ConcreteDecorator2();
    8. Decorator d=(Decorator) ReadXML.getObject();
    9. ProjectManager m=new ProjectManager(d);
    10. Parlour p=m.decorate();
    11. p.show();
    12. } catch (Exception e) {
    13. System.out.println(e.getMessage());
    14. }
    15. }
    16. }
            2.8 UML图

    三、代码结构图

  • 相关阅读:
    回顾总结之数据结构:3 链表
    idea不能设置包名为con
    Linux——进程信号
    现代 CSS 解决方案:CSS 原生支持的三角函数
    OpenCV模板匹配实现银行卡数字识别
    【SQL性能优化】Hash索引的底层原理是什么?
    PreScan快速入门到精通第三十一讲基于PreScan进行鱼眼摄像头传感器仿真
    【前端设计模式】之命令模式
    企业级监控方案——zabbix!(上)
    使用python-docx完成word操作
  • 原文地址:https://blog.csdn.net/qq_45276194/article/details/137920331