当前位置: 首页 > news >正文

设计模式(4)之建造者模式

  建造者模式是最复杂的创建型模式,它用于创建一个包含多个组成部分的复杂对象,可以返回一个完整的产品对象给用户,建造者模式关注该复杂对象是如何一步一步创建而成的,对于用户而言,无需知道创建过程和内部组成细节,只需要使用创建好的完整对象即可
     
     复杂对象相当于一辆有待建造的汽车,而对象的属性相当于汽车的部件,建造产品的过程就相当于组装部件的过程。由于组装部件过程很复杂,因此,这些部件的组装过程被“外部化”到一个称作建造者的对象里,建造者返回客户端的是一个建造完成的完整的产品对象,而用户无需关心该对象所包含的属性以及他们的组装方式,这就是建造者模式的模式动机。
 
     将一个复杂对象的构建与他的表示分离,使得同样的构造过程可以创建不同的表示,建造者模式是一步一步创建一个复杂的对象,他允许用户只通过复杂对象的类型和内容就可以创建他们,用户不需要知道内部创建的具体细节。
 
     案例分析:
     描述:kfc创建不同的套餐,套餐是一个复杂对象,它一般包含主食(汉堡、鸡肉卷)和饮料(果汁、可乐)等组成部分,不同的套餐有着不同的组成部分,而kfc的服务员可以根据顾客不同的需求,一步一步的装配这些组成部分,构造一个完整的套餐,然后给顾客。
     
     服务员在这里就相当于建造模式中的指挥类角色,调用不同的建造者完成组装过程,然后将产品给用户
 
     伪代码:
      //产品类meal(套餐),这个就是复杂产品对象,它包括food和dirnk两个成员属性,其中food表示主食,drink表示饮料,还有getter setter方法
     public class Meal
     {
          private string food;
          private string drink;
 
          public void setFood($food)
          {
               $this->food = $food;
          }
          public void setDrink($dirnk)
          {
               $this->dirnk = $dirnk;
          }
 
          public void getFood()
          {
               return $this->food;
          }
          public void getDrink()
          {
               return $this->dirnk;
          }
     }
     //抽奖建造者者类MealBuilder(套餐建造者类),它是一个抽象类,生命了抽象的部件组装方法buildFood() 和buildDrink(),MeanBuilder抽象类中还定义了meal类型的对象meal,提供工厂方法getMeal返回meal对象
     public abstract class MealBuilder
     {
          protected $meal = new meal();
 
          public abstract void builderFood();
          public abstract void builderDrink();
          
          public meal getMeal()
          {
               return $this->meal;
          }
     }
     //具体建造者类SubMealBuilderA,(套餐A的创建者),它是抽象类MealBuilder的子类,实现了在抽象父类中声明的builderFood和builderDrink的部件组装方法,该套餐有一个汉堡和一个肌肉卷组成
     public class SubMealBUilderA extends MealBuilder
     {
          public void builderFood()
          {
               $this->meal->setFood('一个汉堡');
          }
          public void builderDrink()
          {
               $this->meal->setDrink('一杯可乐');
          }
     }
     //具体建造者类SubMealBuilderB,用于创建套餐b,由一个鸡肉卷和一杯果汁组成
     public class SubMealBUilderB extends MealBuilder
     {
          public void builderFood()
          {
               $this->meal->setFood('一个鸡肉卷');
          }
          public void builderDrink()
          {
               $this->meal->setDrink('一杯果汁');
          } 
     }
     //指挥者类KfcWaiter(kfc服务员),在kfc套餐制作工程中,他就是kfc的服务员,在其中定义了一个抽象建造者类型的变量mb,具体建造着类型由客户端制定,在其construct()方法中调用mb对象的部件组装方法和返回meal对象的工厂方法,用于向客户端返回一个包含主食和饮料的完整套餐。
     public class KfcWailter
     {
          private MealBuilder $mb;
          public void setMealBuilder(Mealbuilder $mb)
          {
               $this->mb = $mb;
          }
          public Meal construct()
          {
               $this->mb->builderFood();
               $this->mb->builderDrink();
               return $this->mb->getMeal();
          }
     }
     
      //客户端调用代码
     MealBuilder $mb = new Config::get('use_builder');//获取具体的建造者类并实例化
     kfcWailter $waiter = new KfcWailter();//实例化调用者类
     $wailter->setMealBuilder($mb);//为指挥者设置具体建造者类
     Meal $meal = $wailter->constrcunt();//组装并且返回
 
 
     最后总结:
     1.建造者模式将一个复杂对象的创建于它的表示分离,这样同样的创建过程可以创建不同的而表示。建造者模式是一步一步的创建一个复杂的对象,它允许用户只通过制定复杂对象的类型和内容就可以创建他们,用户不需要知道内部的具体构建细节,建造者模式属于类创建模式。
     2.建造者模式包含如下四个角色:抽象建造者是为具体建造者创建一个产品对象的各个部件指定的抽奖接口,是具体建造者的父类;具体建造者继承抽象建造者,实现父类中各部件的构造和装配方法,定义它创建的复杂对象;产品抉择就是那个药构建的复杂的对象,包含多个部件;指挥者负责安排复杂对象的建造次序,指挥者与抽奖建造者存在关联关系,指挥着面向抽象编程,通过调用具体建造者方法完成复杂对象的构造。
     3.在建造者模式中引入了一个指挥者类,该类的作用主要有两个:第一是隔离客户与生产的过程;第二是它复杂产品的创建过程。指挥者只对抽奖编程,客户端只需要知道要构建的复杂对象的类型,即可通过指挥者类调用创建者的相关方法完成产品的构建。
     4.建造者模式的主要优点在于客户端不需要知道产品内部具体的创建过程,将产品本身与创建过程解耦,是相同的创建过程可以创建不同的产品,每一个具体的建造者都是相互独立,与其他建造者无关,因此可以在系统中方便的通过替换建造者或者增加具体的建造者来完成需求变更,符合开闭原则,还可以更加精细的控制产品的创建过程;主要缺点是由于建造者模式所创建的产品一般具有较多的共同点,其组成部分形似,因此在使用范围上受到了一定程度的限制,如果产品内部变化过于复杂,那么可能导致需要定义很多建造者类来实现这种变化,从而导致系统变得庞大臃肿 不利于维护.
     5.建造者模式使用情况包括:需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性;需要生成的产品对象的属性相互依赖,需要指定其生成顺序,对象的创建过程独立于创建该对象的类;隔离复杂对象的创建和使用,并使得相同的创建过程可以创建出不同的产品对象。

转载于:https://www.cnblogs.com/azheng007/archive/2012/08/24/2653721.html

相关文章:

  • 保护模式下中断或异常示意图
  • java override overload
  • 多路访问网络中的挑战
  • 模拟系统提示框
  • DSL概念、类别、为什么要写DSL 1
  • Javascript 日期格式化
  • 成绩单课程翻译参考总表
  • NYOJ 86
  • C#处理oracle数据库的Clob类型
  • I have a dream
  • [笔记]8组LVDS_TX和LVDS_RX的调试心得
  • Struts2数据传输的背后机制:ValueStack(值栈)
  • A Medical Study Tool Developed with WPF
  • POJ题目分类---模拟[A一道删一道]
  • EJB之JPA(UUID与TABLE影射策略)
  • 2017 年终总结 —— 在路上
  • Hibernate最全面试题
  • iOS编译提示和导航提示
  • JavaScript服务器推送技术之 WebSocket
  • sessionStorage和localStorage
  • 第三十一到第三十三天:我是精明的小卖家(一)
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 一个6年java程序员的工作感悟,写给还在迷茫的你
  • 云大使推广中的常见热门问题
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (三)uboot源码分析
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (一)Linux+Windows下安装ffmpeg
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .libPaths()设置包加载目录
  • @软考考生,这份软考高分攻略你须知道
  • [ C++ ] STL priority_queue(优先级队列)使用及其底层模拟实现,容器适配器,deque(双端队列)原理了解
  • [ C++ ] STL---stack与queue
  • [ 环境搭建篇 ] 安装 java 环境并配置环境变量(附 JDK1.8 安装包)
  • [ 英语 ] 马斯克抱水槽“入主”推特总部中那句 Let that sink in 到底是什么梗?
  • [2017][note]基于空间交叉相位调制的两个连续波在few layer铋Bi中的全光switch——
  • [Android]Tool-Systrace
  • [AndroidStudio]_[初级]_[修改虚拟设备镜像文件的存放位置]
  • [AX]AX2012 SSRS报表Drill through action
  • [BZOJ2281][SDOI2011]黑白棋(K-Nim博弈)
  • [C#]使用PaddleInference图片旋转四种角度检测
  • [EFI]Dell Latitude-7400电脑 Hackintosh 黑苹果efi引导文件
  • [Everyday Mathematics]20150130
  • [IE编程] 如何设置IE8的WebBrowser控件(MSHTML) 的渲染模式
  • [Java基础] Java中List.remove报错UnsupportedOperationException
  • [LeetCode] Binary Tree Preorder Traversal 二叉树的先序遍历
  • [LeetCode]—Permutations 求全排列
  • [MAT]使用MAT比較多个heap dump文件
  • [office] 怎么在Excel2003菜单栏自定义一个选项卡 #其他#微信#知识分享