如何使用设计模式来构造系统--(7)

(声明:本系列所用的模式都来自GOF23中,本系列并不是讲23种经典设计模式,而是如何去使用这些模式)   

 

在前面的文章中,我们设计完成了员工工资,福利以及按照部门来区分员工,以及遍历统计部门人员成本等业务逻辑,这些设计基本上可以满足我们所设定的场景的变化,可是创建部门及人员树的时候太复杂了,而且这种创建很容易发生变化,比如加入分公司,或者部门层级变动添加了层级的时候,创建的代码一定就要修改.那么如何避免,封装这个创建时的变化呢?

 

1.分析:来看看我们的意图,我们要将复杂的部门创建过程封装,使得同样的构建过程可以创建不同的部门.那么我们就需要把创建单独封装,创建的过程也需要单独封装.

 

Gof23中的Builder(生成器)模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 与我们的意图相符.那么我们就来使用Builder模式.

 

2.类图:

 

 

3.代码

 

首先封装创建过程:

ContractedBlock.gifExpandedBlockStart.gifCode
public abstract class CompositeBuilder   //封装创建过程
{
    
public abstract PersonComposite BuildComposite();
}

public class Builder:CompositeBuilder  //实现具体的创建过程
{
    
public override PersonComposite BuildComposite()  
    {
        PersonComposite root 
= new PersonComposite();
        StaffAndSalaryFactory saf 
= new StaffAndSalaryFactory();  //实例化工厂
        for (int j = 0; j < 5;j++ )
        {
            PersonComposite pc 
= new PersonComposite();
            pc.Name 
= j.ToString();
            
for (int i = 0; i < 10; i++)
            {
                AbstractPerson staff 
= saf.GetPerson();  //创建员工
                staff.PersonName = "  涵舍愚人"+j.ToString()+i.ToString();
                staff.PersonSalary 
= saf.GetSalary();//创建员工工资
                if (i % 2 == 0)
                {
                    staff.PersonSalary.Salaryprize 
= BadPrize.badPrize;//使用单件初始化员工工资的绩效部分
                    
//该员工工资为:6000+绩效3000=9000
                }
               
else
                {
                    staff.PersonSalary.Salaryprize 
= GoodPrize.goodPrize;//使用单件初始化员工工资的绩效部分
                    
//该员工工资为:6000+绩效6000=12000
                }
                pc.AddComposite(staff);
//将Staff加到部门PC
            }
            root.Composite.Add(pc);
        }
        
return root;
    }
}

 

 

封装创建:

ContractedBlock.gifExpandedBlockStart.gifCode
public class Director  //封装创建
{
    
public PersonComposite GetPersonComposite(CompositeBuilder cb)
    {
         
return cb.BuildComposite();
    }
}

 

客户代码:

 

ContractedBlock.gifExpandedBlockStart.gifCode
class Program
    {
        
static void Main(string[] args)
        {
            Builder b 
= new Builder(); //实例化具体Builder
            Director d = new Director();  //实例化Composite的创建
            PersonComposite pc = d.GetPersonComposite(b);  //用d对象的固定方法创建PersonComposite
            Print(pc); //调用输出
            Console.Read();
        }
        
public static void Print(PersonComposite pc)
        {
            Listterator list 
= new Listterator(pc);  //实例化一个遍历器,用来遍历Composite的子节点
            while (list.Next())  //遍历下一个节点
            {
                PersonComposite spc 
= list.Current() as PersonComposite;//如果是部门,输出部门名字
                if (!Equals(spc, null))
                {
                    Console.Write(
"部门"+spc.Name+"\r\n");  
                    Print(spc); 
//如果是部门,则递归
                }
                
else
                {
                    AbstractPerson ap 
= list.Current() as AbstractPerson;  //如果是人员,输出人员和工资
                    if (!Equals(ap, null))
                    {
                        Console.Write(ap.PersonName 
+ "应得工资为" + ap.GetShouldpaid().ToString()+"\r\n");
                    }
                }

            }
        }
    }

 

我们现在把创建过程封装在了Build类里,当然这里可以是多个步骤,比如创建部门,创建组,创建人员等.

 

将创建完成Composite放到了Director类的固定方法中,我们可以先创建部门,然后组,再然后人员,甚至可以反过来,这样创建过程不变,而Director的GetPersonComposite方法的创建步骤不同,就可以创建出不同的树.这样即使需求变化了,客户代码也不需要去改变,只要去创建不同的Builder和修改Director的方法就好了,如果Director用工厂方法来做,那么连它都不需要修改,而直接添加就好了,设计模式的原则之一就是添加优于修改.

 

输出结果:

 

 

在创建时,给人员名字前加了个空格,就出现了一个简单的树,如果要写树,可以用我们前面用过的Stratege,来封装树控件前面的那小加号,减号,竖线等,然后在创建中使用这些封装的策略.就OK了

 

这样我们就完成了复杂的Composite的创建的封装,但是这里面还有缺点:前面我们说了一个人可能身兼二职,尤其管理层的,更有这个可能,那么他就要出现在不同部门里,而我们现在的创建是一个节点一个对象,这样我们就要浪费内存了...怎么解决?下一篇中我们将介绍!

 

    下一篇:如何使用设计模式来构造系统--(8)

 

转载于:https://www.cnblogs.com/xugao918/archive/2008/08/20/1272228.html

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

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

相关文章

spring mvc学习(32):原生代码导入

第一种方法 1点击项目--右键---preferences(添加build path) 勾上 第二种方法 2配置pom.xml <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</…

深度学习03-CNN 应用

说明&#xff1a;本系列是七月算法深度学习课程的学习笔记 文章目录1 概述2 图片识别定位3 物体监测3.1 选择性搜索3.2 R-CNN3.3 Fast R-CNN3.4 Faster R-CNN4 语义分割4.1 滑窗处理4.2全卷积神经网络5 代码1 概述 CNN主要任务包含物体识别定位、物体识别、图像分割。 图片识…

【转帖】windows命令行中java和javac、javap使用详解(java编译命令)

windows命令行中java和javac、javap使用详解(java编译命令) 更新时间&#xff1a;2014年03月23日 11:53:15 作者&#xff1a; 我要评论 http://www.jb51.net/article/48380.htm学习一下java 最近重新复习了一下java基础&#xff0c;这里便讲讲对于一个类文件如何编译、运行…

第六课 从词向量到NLP分类问题

文章目录1 nlp的常见任务2 词向量表示2.1 离散表示2.2 分布式表示2.3 NNLM(2013年)2.3.1模型2.3.2特点2.4 Word2Vector&#xff1a;CBOW连续词袋2.4.1 样本处理2.4.2 结构2.4.3 CBOW&#xff1a;层次softmax2.4.4 CBOW&#xff1a;负例采样2.4.5 Word2Vec&#xff1a;skip-gram…

spring mvc学习(34):restful的delete

创建maven项目就不说了&#xff0c;需要的找我前面的博客 pom.xml文件 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http…

热度3年猛增20倍,Serverless云开发的技术架构全解析

『 作为一个不断发展的新兴技术&#xff0c; Serverless 热度的制高点已然到来。』 或许&#xff0c;Google Trends 所显示的 3 年猛增 20 倍的“ Serverless ” 搜索量&#xff0c;可以佐证 Serverless 在整个行业中的火爆程度。 不仅如此&#xff0c;据 KBV 研究公司新发布的…

第七课 循环神经网络与自然语言处理

文章目录1 循环神经网络1.1 场景与多种应用1.2 RNN网络结构1.2.1为什么需要RNN1.2.2 RNN 结构1.3 多种RNN1.4 BPTT算法1.5 生成模型与图像描述2 LSTM2.1 LSTM2.2 GRU1 循环神经网络 1.1 场景与多种应用 1 模仿论文生成 2 模仿linux内核编写代码 3 模仿小四写论文 4 机器翻译 …

第十二题:设int x=1,float y=2,则表达式x/y的值是:

第十二题 设int x1,float y2,则表达式x/y的值是&#xff1a;&#xff08;&#xff09; A 0 B 1 C 2 D 以上都不是 懵逼树上懵逼果&#xff0c;懵逼树下你和我 首先看到这道题&#xff0c;我是懵逼和绝望的。 首先我们打开评论&#xff0c;看看谁的赞最多&#xff0c;拿…

Linux 安装 lanmp

Lanmp介绍 lanmp一键安装包是wdlinux官网2010年底开始推出的web应用环境的快速简易安装包. 执行一个脚本&#xff0c;整个环境就安装完成就可使用&#xff0c;快速,方便易用,安全稳定 lanmp一键安装包是用shell脚本编写,且是开源的,你也可以根据业务需求,做相应的调整,来安装自…

如何利用Featue对特定的文档库或列表添加listviewtoolbar上的button

名字有点长&#xff0c;实在想不出什么好名字。 我们经常会遇到一个问题&#xff0c;就是需要在某一个列表或者文档库视图画面的listviewtoolbar上添加一个按钮来做一些操作。比如说页面跳转&#xff0c;列表操作等。目前很多人都知道利用Feature来添加这个button&#xff0c;而…

第八课 RNN条件生成与Attention机制

文章目录1 RNN条件生成2 机器翻译2.1 V1:Encoder-Decoder2.2 V2:Attention-based Encoder-decoder2.3 V3&#xff1a;bi-directional encode layer2.4 V4&#xff1a;Residual Encode layer3 Attention3.1 self attention3.2 hierarchical attention4 图像生成文本4.1 问题引入…

第十四题: 以下代码的输出结果是?

第十四题: 以下代码的输出结果是&#xff1f; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class B { public static B t1 new B(); public static B t2 new B(); { System.out.println("构造块"); } static { Syst…

第一百二十三期:免费在线制图神器!不上水印支持中文版,GitHub标星已破1万2

又一免费制图神器来袭&#xff01;打开网页就能使用&#xff0c;支持中文版&#xff0c;也不会给你上水印。 作者&#xff1a;乾明 又一免费制图神器来袭&#xff01; 名为draw.io&#xff0c;打开网页就能使用&#xff0c;支持中文版&#xff0c;也不会给你上水印。 不只是…

常用javascript脚本

BS开发中常用的Javascript技术 一、验证类 1、数字验证内 1.1 整数 1.2 大于0的整数 &#xff08;用于传来的ID的验证) 1.3 负整数的验证 1.4 整数不能大于iMax 1.5 整数不能小于iMin 2、时间类 2.1 短时间&#xff0c;形如 (13:04:06) 2.2 短日期&#xff0c;形…

第一百二十四期:2019年臭名昭著的勒索软件,网络钓鱼和僵尸网络

Webroot发布了年度恶意软件列表&#xff0c;展示了2019年最臭名昭著的网络安全威胁。从攻击次数最多的勒索软件和加密挖矿&#xff0c;到破坏最大的网络钓鱼攻击&#xff0c;显然&#xff0c;全球网络威胁正在变得更为先进且难以预测。 作者&#xff1a;kirazhou 勒索软件 在…

好久没发胡说八道的贴了,今天发一贴

看了老翅寒暑 [真实案例&#xff1a;给所有想要创业的朋友的一个管理方面的测试题]一贴http://www.cnblogs.com/BigTall/archive/2006/12/20/597896.html这是一个真实的事件&#xff0c;我把它转化为了一个测试题目&#xff0c;问过很多朋友&#xff0c;到目前为止我认为答满分…

N元语法模型的数据稀疏问题解决方法之一:Good-Turing平滑

转载自时空霹雳 在统计语言模型章节中&#xff0c;我们谈到了N元语法模型不可避免的一个问题&#xff0c;就是数据稀疏&#xff0c;其原因是大规模语料统计与有限语料的矛盾。根据齐普夫&#xff08;Zipf&#xff09;法则&#xff0c;我们能够推测知零概率问题不可避免。数据稀…

错误: 在类中找不到 main 方法, 请将 main 方法定义为:public static void main(String[] args)否则 JavaFX 应用程序类必须扩展javafx.ap

最近在使用eclipse编写java程序时遇到这样一个问题&#xff1a; 错误在类中找不到main方法&#xff0c;请将main方法定义为 public static void main(String[] args)否则 JavaFX 应用程序类必须扩展javafx.application.Application 看到这样的问题让我一头雾水&#xff0c;因为…

第十章 条件随机场CRF

文章目录1 条件随机场定义1.1 马尔科夫随机场1.1.1 用图模型表示概率1.1.3 三个马尔科夫性1.1.3 重点再看局部马尔科夫性1.2 马尔科夫随机场的因子分解1.3 条件随机场1.4 线性链条件随机场2线性链条件随机场的表示形式2.1 参数化形式2.2 简化形式2.3 矩阵形式3 条件随机场的概率…

第一百二十五期:程序员的自我救赎,使用Python开发性格分析工具

如此不均衡的贫富差距&#xff0c;各行业的领导者如何能管理好公司&#xff0c;让员工们既努力产出&#xff0c;又能安于现状呢?每个领导者必学的一门课程就是职场心理学。只有你充分了解员工心理与对应的行为表现&#xff0c;才能从容的掌控各类型的人员&#xff0c;从而达到…