您的位置:首页 > 其它

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

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

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

1.分析

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

2.过滤

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

3.设计

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

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

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



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

代码:

Icomposite,Composite:




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:




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();

}

}

客户代码:




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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: