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

博客围绕客户提出的统计公司、部门或小组薪资成本的需求展开。先通过名词分析法分析需求,过滤出相关名词,考虑到未来可能的层级变化,决定统一处理。最终选用GOF23中的Composite模式进行设计,使组织和人员操作一致,还对比了该模式与Decorator模式。

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

 

 

前面我们设计了员工的工资,奖金,福利系统。今天客户又来增加需求了:"我们需要统计公司,部门,或者小组的薪资成本。"得到了需求,我们还是按照老套路来完成我们的设计。

 

 

1.分析

我们用"名词分析法"来分析需求里面的类(第一篇有讲解),薪资的部分我们已经有了,需求中包含公司,部门,小组这三个名词。好的我们来过滤它。 

 

2.过滤

好,我们通过分析得到了公司,部门,小组。这里要考虑以后可能有的变化,最常见的是公司去添加一个层级,比如添加一个分公司。我们不能把公司,部门,小组,分别当成一个类来处理,这样添加层级的时候,我们又要重新写代码,然后编译发布,这是我们要极力避免的。那么怎么去做呢?其实说白了,公司的组织结构都是由Person组成的,一个树形结构。我们可以把它们统一起来,让客户程序在使用公司,部门,小组,或者人的时候具有统一性。那么我们就设计一个类就足够了。

 

3.设计

我们来看客户的话:"我们需要统计公司,部门,或者小组的薪资成本",也就是说我们的这个类可能要维护一个人员的列表,然后把它们的工资,福利加起来最后生成一个组织的薪资成本.需要考虑的是很有可能一个人不属于任何部门,也就是说他和公司平级,或者不属于任何小组,他和部门平级,所以这里我们对待组织和对待人必须要一样,否则我们只能去遍历判断这个节点下到底是个组织还是员工。总结一下我们的设计意图:我们希望形成一个树层次结构,而且要让组织的操作和人员的操作一样。怎么做??

 

GOF23中的Composite(组合):将对象组合成树形结构以表示“部分-整体”的层次结构。使得用户对单个对象和组合对象的使用具有一致性。 与我们的意图相符,OK,就是它,我们开始具体设计吧!

 

4.类图(为了回顾前面的设计,这次贴出设计全部类图,本篇的设计看红色框起来的部分)

 

 

 

 

我们设计了一个接口Icomposite,并且让Person,PersonComposite继承自它

 

代码:

Icomposite,Composite:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
public interface IComposite
{
    
double GetShouldpaid();
}

public class PersonComposite :IComposite
{
    
private ArrayList  composite=new ArrayList();  //维护一个Icomposite的列表
    public void AddComposite(IComposite com)
    {
        composite.Add(com); 
//添加一个Icomposite的子类
    }
    
public void RemoveComposite(IComposite com)
    {
        composite.Remove(com); 
//删除一个Icomposite 的子类
    }
    
public  double GetShouldpaid()
    {
        
double x=0;
        
for (int i = 0; i < composite.Count; i++)  //遍历当前维护的Icomposite的列表
        {
            IComposite com 
= (IComposite)composite[i];
            x 
+= com.GetShouldpaid();  //递归到当前列表i元素的GetShouldpaid
        }
        
return x;
    }
}

 

Person:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
public abstract class AbstractPerson :IComposite
{
    
protected string _personName;  //员工姓名
    protected Salary _personSalary; //员工工资

     
public string PersonName
    {
        
get { return _personName; }
        
set { _personName = value; }
    }
     
public Salary PersonSalary
     {
         
get { return _personSalary; }
         
set { _personSalary = value; }
     }

     
public abstract double GetShouldpaid();   
}

public  class Staff : AbstractPerson
{
    
public override double GetShouldpaid()  //实现具体的Staff的工资
    {
        
return _personSalary.GetShouldpaid();
    }
}
public class Internship : AbstractPerson
{

    
public override double GetShouldpaid() //实现实习者的工资
    {
        
return _personSalary.GetShouldpaid();
    }
}

 

客户代码:

 

 

ContractedBlock.gif ExpandedBlockStart.gif Code
class Program
    {
        
static void Main(string[] args)
        {
            StaffAndSalaryFactory saf 
= new StaffAndSalaryFactory();  //实例化工厂
            AbstractPerson staff1 = saf.GetPerson();  //创建员工
            staff1.PersonName = "涵舍愚人1";
            staff1.PersonSalary 
= saf.GetSalary();//创建员工工资
            staff1.PersonSalary.Salaryprize = BadPrize.badPrize;//使用单件初始化员工工资的绩效部分
            
//该员工工资为:6000+绩效3000=9000

            AbstractPerson staff2 
= saf.GetPerson();  //创建员工
            staff2.PersonName = "涵舍愚人2";
            staff2.PersonSalary 
= saf.GetSalary();//创建员工工资
            staff2.PersonSalary.Salaryprize = GoodPrize.goodPrize;//使用单件初始化员工工资的绩效部分
            
//该员工工资为:6000+绩效6000=12000
           
            
            PersonComposite pc1 
= new PersonComposite();
            pc1.AddComposite(staff1); 
//将Staff1加到小组PC1

            PersonComposite pc2 
= new PersonComposite();
            pc2.AddComposite(pc1); 
//将PC1小组加到部门PC2
            pc2.AddComposite(staff2);//将Staff2加到部门PC2

            Console.Write(
"部门工资开支为:"+pc2.GetShouldpaid());//察看部门PC2的开支
            Console.Read();
        }
    }

 

 

输出结果:

 

 

Composite模式和前面使用的Decorator模式大体上是一样的,对他们的父类都有一个Has-a(拥有)的关系,同时又是Is-a,所以Decorator可以无限添加功能,而Composite也可以无限添加节点,只因它们是同根生...唯一的区别就是:Composite是维护父类列表,Decorator维护了一个父类(其实就是他自己).

 

OK,这样我们完成就了用户的需求,但是还有一些不足,下一篇我们来完善它.

 

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

 

 

转载于:https://www.cnblogs.com/xugao918/archive/2008/08/15/1268546.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值