设计模式之建造者模式与原型模式

news2024/9/24 17:13:46

目录

建造者模式

简介

使用场景

优缺点

模式结构

实现

原型模式

简介

应用场景

优缺点

模式结构

实现


建造者模式

简介

        将复杂对象的构建与表示进行分离,使得同样的构建过程可以创建不同的表示。是一个将复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变分离,即产品的组成部分是不变的,但是每一部分都可以灵活选择。

使用场景

        1.当创建对象复杂时,可以将创建对象的步骤分离出去,使用建造者模式

        2.对于一些复杂的对象,如果对象的属性是由许多不同部分组成的,而这些部分需要按照一定的步骤进行创建,那么就可以使用建造者模式

        3.如果有许多相似的对象需要被创建,而且这些对象的创建过程相同,只是初始值不同,那么就可以使用建造者模式

        4.如果想要创建一个对象,但是对象的创建过程需要使用一些敏感信息,比如密码等,那么就可以使用建造者模式来保证这些敏感信息的安全性

优缺点

优点:

        1.封装性好,构建和表示分离

        2.扩展性好,各个具体的建造者相互独立,有利于系统解耦

        3.客户端不必知道产品内部的组成和细节,建造者可以对创建过程逐步细化,而不对其他模块产生任何影响,便于控制细节风险

缺点:

        1.产品的组成部分必须相同,限制了其使用范围

        2.产品内部发生变化,建造者也要修改,后期维护成本较大

模式结构

角色:

        产品角色:包含多个组成部分的复杂对象,由具体建造者来创建其各个零部件

        抽象建造者:包含创建产品各个子部件的抽象方法接口

        具体建造者:实现 Builder 接口,完成复杂产品的各个部件的具体创建方法

        指挥者:调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息

结构图:

实现

//产品角色:包含多个组成部件的复杂对象

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() {
        //显示产品的特性
    }
}
​
//抽象建造者:包含创建产品各个子部件的抽象方法

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;
    }
}

//具体建造者:实现了抽象建造者接口。
public class ConcreteBuilder extends Builder {
    public void buildPartA() {
        product.setPartA("建造 PartA");
    }
    public void buildPartB() {
        product.setPartB("建造 PartB");
    }
    public void buildPartC() {
        product.setPartC("建造 PartC");
    }
}

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

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

//调用
public class Client {
    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        Product product = director.construct();
        product.show();
    }
}

原型模式

简介

允许通过复制或克隆一个已存在的对象来创建一个新对象,而无需从头开始创建。这种模式在需要生成大量复制相似对象时特别有用。

应用场景

        1.创建新对象成本较大时

        2.系统要保存对象的状态,而对象的状态变化很小

        3.避免使用分层次的工厂类来创建分层次的对象

优缺点

优点:

        1.通过复制已有对象,而不是从头创建,节约了时间和资源

        2.如果对象包含多层嵌套,深复制会消耗太多资源;原型模式通过浅复制,可以避免

        3.可以避免通过构造方法复制时可能出现的错误

不足:

        1.增加了系统的复杂性,需要处理原始对象的复制和克隆操作

        2.复制对象,增加了内存使用量

        3.复制对象时,需确保所有的引用关系都正确的复制了

模式结构

角色:

        抽象原型类:声明克隆方法的接口,是所有具体原型类的公共父类,可以是抽象类、接口和具体的实现类

        具体原型类:实现抽象原型类中声明的克隆方法,在克隆方法中返回一个自己的克隆对象

        客户类:让一个原型对象克隆自己而创建一个新的对象,在客户类中只需要直接实例化或通过工厂方法的创建一个原型对象,再通过该对象的克隆方法即可获得多个相同的对象

实现

1.创建接口抽象类

public abstract class Shape implements Cloneable {
   
   private String id;
   protected String type;
   
   abstract void draw();
   
   public String getType(){
      return type;
   }
   
   public String getId() {
      return id;
   }
   
   public void setId(String id) {
      this.id = id;
   }
   
   public Object clone() {
      Object clone = null;
      try {
         clone = super.clone();
      } catch (CloneNotSupportedException e) {
         e.printStackTrace();
      }
      return clone;
   }
}

2.拓展抽象类的实体类

public class Rectangle extends Shape {
 
   public Rectangle(){
     type = "Rectangle";
   }
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}

public class Square extends Shape {
 
   public Square(){
     type = "Square";
   }
 
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}

public class Circle extends Shape {
 
   public Circle(){
     type = "Circle";
   }
 
   @Override
   public void draw() {
      System.out.println("Inside Circle::draw() method.");
   }
}

3.创建一个类,从数据库获取实体类

import java.util.Hashtable;
 
public class ShapeCache {
    
   private static Hashtable<String, Shape> shapeMap 
      = new Hashtable<String, Shape>();
 
   public static Shape getShape(String shapeId) {
      Shape cachedShape = shapeMap.get(shapeId);
      return (Shape) cachedShape.clone();
   }
 
   // 对每种形状都运行数据库查询,并创建该形状
   // shapeMap.put(shapeKey, shape);
   // 例如,我们要添加三种形状
   public static void loadCache() {
      Circle circle = new Circle();
      circle.setId("1");
      shapeMap.put(circle.getId(),circle);
 
      Square square = new Square();
      square.setId("2");
      shapeMap.put(square.getId(),square);
 
      Rectangle rectangle = new Rectangle();
      rectangle.setId("3");
      shapeMap.put(rectangle.getId(),rectangle);
   }
}

4.进行克隆

public class PrototypePatternDemo {
   public static void main(String[] args) {
      ShapeCache.loadCache();
 
      Shape clonedShape = (Shape) ShapeCache.getShape("1");
      System.out.println("Shape : " + clonedShape.getType());        
 
      Shape clonedShape2 = (Shape) ShapeCache.getShape("2");
      System.out.println("Shape : " + clonedShape2.getType());        
 
      Shape clonedShape3 = (Shape) ShapeCache.getShape("3");
      System.out.println("Shape : " + clonedShape3.getType());        
   }
}

与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。

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

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

相关文章

Elasticsearch分布式搜索结果处理

1.排序 elasticsearch默认是根据相关度算分&#xff08;_score&#xff09;来排序&#xff0c;但是也支持自定义方式对搜索结果排序。可以排序字段类型有&#xff1a;keyword类型、数值类型、地理坐标类型、日期类型等。 1.1.普通字段排序 keyword、数值、日期类型排序的语法…

四季同行·雷锋家乡学雷锋“青柚课堂“讲师培训

为了给益阳市“青柚课堂”性教育志愿者讲师团队增加新鲜血液&#xff0c;8月27日&#xff0c;我机构在益阳市红十字救护培训基地开展了湖南省第二期"四季同行雷锋家乡学雷锋"孵化项目"青柚课堂"乡村女童性教育推广计划2023年师资培训。本次活动由我机构“蚂…

虹科方案 | 车辆零部件温度采集解决方案

虹科提供的车辆零部件温度监控与采集解决方案&#xff0c;通过热电偶模块来采集、监控、处理温度数据&#xff0c;可以通过CAN / CAN FD进行传输&#xff0c;确保车辆系统的正常运行和安全性。 文章目录 一、热电偶在汽车领域的应用什么是热电偶模块&#xff1f;热电偶模块如何…

PSP - 蛋白质结构预测 OpenFold Multimer 训练模型的数据加载

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132597659 OpenFold Multimer 是基于深度学习的方法&#xff0c;预测蛋白质的多聚体结构和相互作用。利用大规模的蛋白质序列和结构数据&#xff…

Unity 顶点vertices,uv,与图片贴图,与mesh

mesh就是组成3d物体的三角形们。 mesh由顶点组成的三角形组成&#xff0c;三角形的大小 并不 需要一样&#xff0c;由顶点之间的位置决定。 mesh可以是一个或者多个面。 贴图的原点在左下角&#xff0c;uv是贴图的坐标&#xff0c;数量和顶点数一样&#xff08;不是100%确定…

Unity MonoBehaviour事件函数的生命周期

Unity运行时候的默认的几个函数的执行顺序&#xff1a; 首先是Awake&#xff0c;OnEnable&#xff0c;Start等&#xff0c;后面是FixUpdate Update 最后是OnDisable、OnDestroy

《CTFshow-Web入门》09. Web 81~90

Web 入门 索引web81题解 web82题解原理 web83题解 web84题解 web85题解 web86题解 web87题解原理 web88题解 web89题解 web90题解 ctf - web入门 索引 web81&#xff1a;include() 利用&#xff0c;一句话木马之 Nginx 日志利用。web82~86&#xff1a;include() 利用&#xff…

pyqt5的 Qprogressbar 如何设计得好看一些?

参考官网内容 style 自定义&#xff1a; https://doc.qt.io/qtforpython-5/overviews/stylesheet-examples.html#customizing-qprogressbar 1.圆角&#xff0c;浅蓝色 QProgressBar {border: 2px solid grey;border-radius: 5px; }QProgressBar::chunk {background-color: #0…

Halo2、Caulk+、Baloo、Cq Lookup argument细览

1. 引言 本文主要参考2023年2月以太坊基金会Mary Maller在第13届 BIU Winter School on Cryptography上的视频分享 A Close Look at a Lookup Argument - Mary Maller。 以证明 0 ≤ x < 4 0\leq x <4 0≤x<4为例&#xff0c;相比于使用算术化电路中如何使用定制gat…

免费s5爬虫ip:真正靠谱还是泡沫?

在网络世界中&#xff0c;许多人寻找免费的s5爬虫ip以实现匿名上网和绕过地域限制。然而&#xff0c;关于这些免费服务的可信度一直存在争议。本文将探讨免费s5爬虫ip背后的真相&#xff0c;并帮助您判断它们到底是值得依赖还是只不过虚幻泡沫。 1、充斥着风险 大部分提供免费…

不平衡的数据集将如何影响模型的性能?示例说明

一、说明 朋友们&#xff0c;您可能听说过&#xff0c;在不平衡数据集上训练的模型可能会受到泛化不佳和少数类检测减少的影响。在接下来的几篇文章中&#xff0c;我将给你一个例子来展示不平衡的数据集如何影响模型的性能&#xff0c;以及我们如何处理这个问题。在这篇文章中&…

【pdf密码】忘记了密码该如何编辑PDF文件?

PDF文件设置了密码&#xff0c;无法编辑PDF文件&#xff0c;如果忘记了PDF密码&#xff0c;无法取消限制编辑&#xff0c;那么这种情况&#xff0c;我们该如何解决&#xff1f;分享两个方法。 方法一&#xff1a; 将PDF文件转换为其他格式&#xff0c;这里&#xff0c;我们可…

Navicat:解决导入csv文件中文乱码的问题

文章目录 1 问题描述2 解决方案 1 问题描述 导入时编码格式默认选择UTF-8 后面发现源字段中文显示乱码 2 解决方案 用记事本txt格式打开csv文件&#xff0c;查看右下角编码格式是否为UTF-8 一般通过xls另存的csv&#xff0c;编码格式为ANSI&#xff0c;需要转换为UTF-8 转…

解决小程序中textarea ios端样式不兼容的方法

问题描述 &#xff0c;今天在调试小程序的时候有个需求需要textarea与标题对其&#xff0c;微信开发工具和安卓系统都没有问题 但是ios系统textarea存在内边距。出现不兼容的情况 解决方法&#xff1a;我们看官网的textarea的属性 textarea | uni-app官网 disable-default-p…

插座上亚马逊美国站UL1449测试报告标准

美规插座有UL498&#xff1b;UL1363&#xff1b;UL1449等标准。不同结构&#xff1b;不同形式使用的标准不同。UL498插座部分主要是对结构和常规性测试的要求&#xff1b;此类插座称为Receptacle&#xff1b;UL1363主要是对室内用的延长线插座的要求&#xff1b;此类插座常简写…

基于ssm+vue舞蹈网站的设计与实现

基于ssmvue舞蹈网站的设计与实现111 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技…

开发指导—利用CSS动画实现HarmonyOS动效(一)

注&#xff1a;本文内容分享转载自 HarmonyOS Developer 官网文档 一. CSS 语法参考 CSS 是描述 HML 页面结构的样式语言。所有组件均存在系统默认样式&#xff0c;也可在页面 CSS 样式文件中对组件、页面自定义不同的样式。请参考通用样式了解兼容 JS 的类 Web 开发范式支持的…

易基因:De novo组装和转录组表征:东方田鼠原发性卵巢癌机制新见解|项目文章

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 2022年&#xff0c;中南大学湘雅医学院周智君教授团队在Mol Med Rep发表了题为" De novo assembly and transcriptome characterization: Novel insights into the mechanisms of p…

PDF转成翻页的电子图册?或许这样做你也可以

PDF转成翻页的电子图册是一种很有趣的方式&#xff0c;可以让读者像翻阅实体书一样浏览电子文档。这种形式的电子图册可以通过将PDF文件转换为HTML5格式来实现翻页效果。这样做的好处是可以增加用户的阅读体验&#xff0c;使阅读更加生动有趣。 如果你也想转换成翻页的电子图册…

首批!八家大模型企业面向全民开放

Datawhale干货 开放&#xff1a;国产大模型&#xff0c;编辑&#xff1a;司玉鑫 前 言 在科技领域&#xff0c;一项重要的消息引起了广泛关注&#xff1a; 8月31日凌晨&#xff0c;首批大模型产品终于获得了正式批准。这一消息不仅令行业内的巨头企业欢欣鼓舞&#xff0c;也使…