分公司=-部门--组合模式

news2025/1/11 23:51:52

1.1 分公司不就是一部门吗?

        "我们公司最近接了一个项目,是为一家在全国许多城市都有分销机构的大公司做办公管理系统,总部有人力资源、财务、运营等部门。"
        "这是很常见的OA系统,需求分析好的话,应该不难开发的。"
        "是呀,我开始也这么想,这家公司试用了我们开发的系统后感觉不错,他们希望可以在他们的全部分公司推广,一起使用。他们在北京有总部,在全国几大城市设有分公司,比如上海设有华东区分部,然后在一些省会城市还设有办事处,比如南京办事处、杭州办事处。现在有个问题是,总公司的人力资源部、财务部等办公管理功能在所有的分公司或办事处都需要有。你说怎么办?"
        "你打算怎么办呢?"大鸟不答反问道。
        "因为你之前讲过简单复制是最糟糕的设计,所以我的想法是共享功能到各个分公司,也就是让总部、分公司、办事处用同一套代码,只是根据ID的不同来区分。"
"要糟了。"


        "你怎么知道?的确是不行,因为他们的要求,总部、分部和办事处是成树状结构的,也就是有组织结构的,不可以简单地平行管理。这下我就比较痛苦了,因为实际开发时就得一个一个地判断它是总部,还是分公司的财务,然后再执行其相应的方法。"
        "你有没有发现,类似的这种部分与整体情况很多见,例如卖电脑的商家,可以卖单独配件,也可以卖组装整机,又如复制文件,可以一个一个文件复制粘贴,还可以整个文件夹进行复制,再比如文本编辑,可以给单个字加粗、变色、改字体,当然也可以给整段文字做同样的操作。其本质都是同样的问题。"
        "你的意思是,分公司或办事处与总公司的关系,就是部分与整体的关系?"
        "对的,你希望总公司的组织结构,比如人力资源部、财务部的管理功能可以复用于分公司。这其实就是整体与部分可以被一致对待的问题。"
        "哈,我明白了,就像你举的例子,对于Word文档里的文字,对单个字的处理和对多个字甚至整个文档的处理,其实是一样的,用户希望一致对待,程序开发者也希望一致处理。但具体怎么做呢?"
        "首先,我们来分析一下你刚才讲到的这个项目,如果把北京总公司当作一棵大树的根部的话,它的下属分公司其实就是这棵树的什么?"
        "是树的分枝,哦,至于各办事处是更小的分支,而它们的相关的职能部门由于没有分枝了,所以可以理解为树叶。"


        "尽管天下没有两片相同的树叶,但同一棵树上长出来的树叶样子也不会相差到哪去。也就是说,你所希望的总部的财务部管理功能也最好是能复用到子公司,那么最好的办法就是,我们在处理总公司的财务管理功能和处理子公司的财务管理功能的方法都是一样的。"

1.2 组合模式

        组合模式(Composite),将对象组合成树形结构以表示'部分-整体'的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。[DP]
组合模式(Composite)结构图

        组合模式(Composite),将对象组合成树形结构以表示'部分-整体'的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。[DP]
组合模式(Composite)结构图
        Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component的子部件。
        Leaf在组合中表示叶节点对象,叶节点没有子节点。
        Composite定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加add和删除remove。
        客户端代码,能通过Component接口操作组合部件的对象。

package code.chapter19.component1;

import java.util.ArrayList;

public class Test {
	
	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

        ConcreteCompany root = new ConcreteCompany("北京总公司");
        root.add(new HRDepartment("总公司人力资源部"));
        root.add(new FinanceDepartment("总公司财务部"));

        ConcreteCompany comp = new ConcreteCompany("上海华东分公司");
        comp.add(new HRDepartment("华东分公司人力资源部"));
        comp.add(new FinanceDepartment("华东分公司财务部"));
        root.add(comp);
        
        ConcreteCompany comp2 = new ConcreteCompany("南京办事处");
        comp2.add(new HRDepartment("南京办事处人力资源部"));
        comp2.add(new FinanceDepartment("南京办事处财务部"));
        comp.add(comp2);
        
        ConcreteCompany comp3 = new ConcreteCompany("杭州办事处");
        comp3.add(new HRDepartment("杭州办事处人力资源部"));
        comp3.add(new FinanceDepartment("杭州办事处财务部"));
        comp.add(comp3);

        System.out.println("结构图:");
        root.display(1);
        System.out.println("职责:");
        root.lineOfDuty();


		System.out.println();
		System.out.println("**********************************************");

	}
}

//公司抽象类
abstract class Company{
    protected String name;
    public Company(String name){
        this.name = name;
    }

    public abstract void add(Company company);      //增加
    public abstract void remove(Company company);   //移除
    public abstract void display(int depth);        //显示
       
    public abstract void lineOfDuty();  //履行职责
}


//具体分公司类,树枝节点
class ConcreteCompany extends Company{
    protected ArrayList<Company> children = new ArrayList<Company>();

    public ConcreteCompany(String name){
        super(name);
    }

    public void add(Company company){
        children.add(company);
    }
    public void remove(Company company){
        children.remove(company);
    }

    public void display(int depth) { 
        for(int i=0;i<depth;i++)
            System.out.print("-");
        System.out.println(name);
        for(Company item : children){
            item.display(depth+2);
        }
    }            
    
    //履行职责
    public void lineOfDuty(){
        for(Company item : children){
            item.lineOfDuty();
        }
    }
}

//人力资源部,树叶节点
class HRDepartment extends Company{
    public HRDepartment(String name){
        super(name);
    }

    public void add(Company company){
    }
    public void remove(Company company){
    }
    public void display(int depth) { 
        for(int i=0;i<depth;i++)
            System.out.print("-");
        System.out.println(name);
    }            
    //履行职责
    public void lineOfDuty(){
        System.out.println(name+" 员工招聘培训管理");
    }
}


//财务部,树叶节点
class FinanceDepartment extends Company{
    public FinanceDepartment(String name){
        super(name);
    }

    public void add(Company company){
    }
    public void remove(Company company){
    }
    public void display(int depth) { 
        for(int i=0;i<depth;i++)
            System.out.print("-");
        System.out.println(name);
    }        
    //履行职责
    public void lineOfDuty(){
        System.out.println(name+" 公司财务收支管理");
    }
}



1.3 透明方式与安全方式

        "树可能有无数的分枝,但只需要反复用Composite就可以实现树状结构了。"
        "有点懂,但还是有点疑问,为什么Leaf类当中也有add和remove,树叶不是不可以再长分枝吗?"
        "是的,这种方式叫作透明方式,也就是说,在Component中声明所有用来管理子对象的方法,其中包括add、remove等。这样实现Component接口的所有子类都具备了add和remove。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为Leaf类本身不具备add()、remove()方法的功能,所以实现它是没有意义的。"
        "哦,那么如果我不希望做这样的无用功呢?也就是Leaf类当中不用add和remove方法,可以吗?"
        "当然是可以,那么就需要安全方式,也就是在Component接口中不去声明add和remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite中声明所有用来管理子类对象的方法,这样做就不会出现刚才提到的问题,不过由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。"
        "我喜欢透明式,那样就不用做任何判断了。"
        "开发怎么能随便有倾向性?两者各有好处,视情况而定吧。"

1.4 何时使用组合模式

        "什么地方用组合模式比较好呢?"
        "当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。"
        "哦,我想起来了。Java开发窗体用的容器控件java.awt.Container,它继承于java.awt.Component,就有add方法和remove方法,所以在它上面增加控件,比如Button、Label、Checkbox等控件,就变成很自然的事情,这就是典型的组合模式的应用。"


        "哦,对的对的,这就是部分与整体的关系。"

1.5 公司管理系统

package code.chapter19.component0;

import java.util.ArrayList;

public class Test {
	
	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

        Composite root = new Composite("root");
        root.add(new Leaf("Leaf A"));
        root.add(new Leaf("Leaf B"));

        Composite comp = new Composite("Composite X");
        comp.add(new Leaf("Leaf XA"));
        comp.add(new Leaf("Leaf XB"));        
        root.add(comp);
        
        Composite comp2 = new Composite("Composite XY");
        comp2.add(new Leaf("Leaf XYA"));
        comp2.add(new Leaf("Leaf XYB"));
        comp.add(comp2);

        Leaf leaf = new Leaf("Leaf C");
        root.add(leaf);

        Leaf leaf2 = new Leaf("Leaf D");
        root.add(leaf2);
        root.remove(leaf2);

        root.display(1);


		System.out.println();
		System.out.println("**********************************************");

	}
}

abstract class Component{
    protected String name;
    public Component(String name){
        this.name = name;
    }

    public abstract void add(Component component);
    public abstract void remove(Component component);
    public abstract void display(int depth);
}

class Leaf extends Component{
    public Leaf(String name){
        super(name);
    }

    public void add(Component component){
        System.out.println("Cannot add to a leaf.");
    }

    public void remove(Component component){
        System.out.println("Cannot remove from a leaf.");
    }

    public void display(int depth){
        //叶节点的具体显示方法,此处是显示其名称和级别
        for(int i=0;i<depth;i++)
            System.out.print("-");
        System.out.println(name);
    }
}

class Composite extends Component{
    private ArrayList<Component> children = new ArrayList<Component>();//一个子对象集合用来存储其下属的枝节点和叶节点

    public Composite(String name){
        super(name);
    }

    public void add(Component component){
        children.add(component);
    }
    public void remove(Component component){
        children.remove(component);
    }
    public void display(int depth){
        //显示其枝节点名称
        for(int i=0;i<depth;i++)
            System.out.print("-");
        System.out.println(name);
        //对其下级进行遍历
        for(Component item : children){
            item.display(depth+2);
        }
    }
}



1.6 组合模式好处

        "组合模式这样就定义了包含人力资源部和财务部这些基本对象和分公司、办事处等组合对象的类层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。"
        "我感觉用户是不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。"
        "简单点说,就是组合模式让客户可以一致地使用组合结构和单个对象。"
"这也就是说,那家公司开多少个以及多少级办事处都没问题了。"哪怕开到地级市、县级市、镇、乡、村、户……"
        "喂,发什么神经了。"大鸟提醒道,"开办事处到户?你有毛病呀。"
        "不过理论上,用了组合模式,在每家每户设置一个人力资源部和财务部也是很正常的。"哪家不需要婚丧嫁娶、增丁添口等家务事,哪家不需要柴米油盐、衣食住行等流水账。"

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

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

相关文章

76、WAF攻防——信息收集识别被动探针代理池伪指纹白名单

文章目录 什么是WAF&#xff1f; WAF&#xff08;Web Application Firewall&#xff09;web应用防火墙 WAF分类&#xff1a; 软件型WAF 以软件的形式安装再服务器上面&#xff0c;可以接触到服务器上的文件&#xff0c;因此就可以检测服务器上是否有webshell&#xff0c;是否…

Javascript - 你在项目中是如何使用闭包的

难度级别:中高级及以上 提问概率:80% 很多初级开发者其实在日常工作中,很少有使用闭包的机会,但这却是一个非常高频的考点,因为对闭包不是特别了解,使用又少,久而久之,就觉得闭包是一个难点。在Javascript中,一个普通方法在执行完毕后…

【Error】Uncaught TypeError: Cannot read properties of undefined (reading ‘get’)

报错原因&#xff1a; 返回值为undefined 解决&#xff1a; vue3可用&#xff1f;

机场数据治理系列介绍(5)民用机场智慧能源系统评价体系设计

目录 一、背景 二、体系设计 1、评价体系设计维度 2、评价体系相关约定 3、评价指标体系框架设计 4、能源利用评价指标 5、环境友好评价指标 6、智慧管控评价指标 7、安全保障评价指标 三、具体落地措施 一、背景 在“双碳”国策之下&#xff0c;各类机场将能源系统建…

20240408在全志H3平台的Nano Pi NEO CORE开发板的eMMC刷Ubuntu Core 16.04

20240408在全志H3平台的Nano Pi NEO CORE开发板的eMMC刷Ubuntu Core 16.04 2024/4/8 20:46 参考资料&#xff1a; https://wiki.friendlyelec.com/wiki/index.php/NanoPi_NEO_Core/zh#.E5.AE.89.E8.A3.85.E7.B3.BB.E7.BB.9F [ OK ] Created slice Slice /system/getty. [ …

JavaScript - 你做过字符串反转吗

难度级别:初级及以上 提问概率:65% 例如有一个字符串本来是“abcde”,那么现在希望可以将其反转,最终的值是“edcba”,该如何做呢? 第一种是将字符串转为数组,利用数组的reverse方法实现元素反转,然后再将数组转为字符串,代码如下 …

K8s学习七(服务发现_2)

Ingress Service 主要用于集群内部的通信和负载均衡&#xff0c;而 Ingress 则是用于将服务暴露到集群外部&#xff0c;并提供灵活的 HTTP 路由规则。在实际应用中&#xff0c;它们通常结合使用&#xff0c;Service 提供内部通信和负载均衡&#xff0c;Ingress 提供外部访问和…

“AI+信创”两翼齐飞,实在智能全面加速自主可控实在智能RPA

近日&#xff0c;实在智能牵手华为昇腾、摩尔线程在信创领域展开紧密合作&#xff0c;共同加速推进AI和信创产业创新发展。 华为昇腾与实在智能达成昇腾原生大模型联合创新合作&#xff0c;基于华为昇腾AI自主创新软硬件平台全栈技术、实在智能自研RPA基础大模型解决方案能力&a…

2024年2月蓝牙耳机线上电商(京东天猫淘宝)综合热销排行榜

鲸参谋监测的综合电商平台&#xff08;淘宝天猫京东&#xff09;蓝牙耳机市场的销售数据已揭晓&#xff01; 根据鲸参谋数据显示&#xff0c;今年2月份&#xff0c;综合电商平台上蓝牙耳机销量累计约657万副&#xff0c;同比去年下滑34%&#xff1b;销售额累计约17亿元&#x…

一条SQL查询语句的执行顺序

SQL常用字段书写顺序 SELECT&#xff1a;选择要查询的列。 FROM&#xff1a;指定数据来源&#xff0c;即表名。 JOIN&#xff1a;根据指定的连接条件将多个表连接在一起。 ON&#xff1a;指定连接条件&#xff0c;即哪些列的值匹配时&#xff0c;应该将两个表中的行组合在一起。…

Rsync——远程同步命令

目录 一、关于Rsync 1.定义 2.Rsync同步方式 3.备份的方式 4.Rsync命令 5.配置源的两种表达方法 二、配置服务端与客户端的实验——下载 1.准备工作 2.服务端配置 3.客户端配置同步 4.免交互数据同步 5.源服务器删除数据是否会同步 6.可以定期执行数据同步 三、关…

【HTML】简单制作一个动态变色光束花

目录 前言 开始 HTML部分 效果图 ​编辑​编辑​编辑​编辑总结 前言 无需多言&#xff0c;本文将详细介绍一段代码&#xff0c;具体内容如下&#xff1a; 开始 首先新建文件夹&#xff0c;创建一个文本文档&#xff0c;其中HTML的文件名改为[index.html]&a…

德兰梅尔:耐高温热销的膜元件亮相2024上海国际生物发酵展

德兰梅尔&#xff1a;耐高温热销的膜元件盛装亮相2024上海国际生物发酵展&#xff0c;8月7-9号上海新国际博览中心与您不见不散&#xff01; 据了解&#xff0c;从成立至今&#xff0c;德兰梅尔一直专注膜技术、膜产品的开发生产。在中国市场上&#xff0c;德兰梅尔刚步入中国…

SpringBoot项目 jar包方式打包部署

SpringBoot项目 jar包方式打包部署 传统的Web应用进行打包部署&#xff0c;通常会打成war包形式&#xff0c;然后将War包部署到Tomcat等服务器中。 在Spring Boot项目在开发完成后&#xff0c;确实既支持打包成JAR文件也支持打包成WAR文件。然而&#xff0c;官方通常推荐将Sp…

【SpringCloud】Nacos 配置管理

目 录 一.统一配置管理1. 在 nacos 中添加配置文件2. 从微服务拉取配置 二.配置热更新1. 方式一2. 方式二 三.配置共享1. 添加一个环境共享配置2. 在 user-service 中读取共享配置3. 运行两个 UserApplication&#xff0c;使用不同的 profile4. 配置共享的优先级5. 多服务共享配…

esp32连接wifi

1、简介 Wi-Fi设备有两种模式&#xff1a; 1.Access Point(AP) 模式&#xff0c;此为无线接入点&#xff0c;家里的光猫就是结合WiFi和internet路由功能的AP。 2.Station(STA)模式&#xff0c;此为 无线终端&#xff0c;连接到AP的装置&#xff0c;手机&#xff0c;电脑等需…

如何用matplotlib画图像的时候使用中文标签名

Matplotlib 中文显示不是特别友好&#xff0c;要在 Matplotlib 中显示中文&#xff0c;我们可以通过两个方法&#xff1a; 下载使用支持中文的字体库。设置 Matplotlib 的字体参数。 下载使用支持中文的字体库: Matplotlib 默认情况不支持中文&#xff0c;我们可以使用以下简…

大语言模型 vs 大模型

前言 有时候我们经常说行业大模型&#xff0c;医疗大模型&#xff0c;开源大模型&#xff0c;甚至用「产品大模型」的固定结构去称呼一个模型&#xff0c;例如百度的文心一言大模型&#xff0c;但是文心一言其实是大语言模型&#xff0c;大模型和大语言模型&#xff0c;差别就…

每天掌握一个软测高级技巧:接口自动化神器apin进阶操作

之前写了一篇关于接口自动化框架 apin 入门使用是文章&#xff0c;主要介绍了 apin 的安装以及用例编写的方法。 今天这篇文章来给大家聊聊&#xff0c;apin 中的一些高级使用技巧。比如依赖接口的变量提取和引用&#xff0c;用例断言&#xff0c;以及函数工具的使用。 变量提…

蓝桥杯刷题-12-公因数匹配-数论(分解质因数)不是很理解❓❓

蓝桥杯2023年第十四届省赛真题-公因数匹配 给定 n 个正整数 Ai&#xff0c;请找出两个数 i, j 使得 i < j 且 Ai 和 Aj 存在大于 1 的公因数。 如果存在多组 i, j&#xff0c;请输出 i 最小的那组。如果仍然存在多组 i, j&#xff0c;请输出 i 最小的所有方案中 j 最小的那…