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

 

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

 

(由于篇幅有限,部分代码请看 如何使用设计模式来构造系统--(1) )

 

前面两篇中,完成了客户所提的"我们的系统要管理人员的工资.(为了模拟真实的开发场景,这里暂时先定义一个功能)人员分为实习员工和正式员工,他们的基本工资是不同的,工资包括基本工资和绩效工资."这样的一个系统需求.我们设计并完成了他,今天客户由于公司要给员工福利,而来追加需求"按照不同的职位,给与不同的福利,一个人可能身兼几个职位".OK,明确了需求,我们还是按照第一篇的方式来完成它.

 

 

1.分析

我们用"名词分析法"来分析需求里面的类(第一篇有讲解),这里出现了职位和福利. 那么我们就得到两个类Duty(职位)和Welfare(福利).

 

2.过滤

好,我们通过分析得到了Person(人员),Duty(职位)和Welfare(福利),这里的福利我们就简化他只是个数字(如果很复杂,可以把它单独做一个类,然后用我们第一篇提到的Bridge模式去把职位和福利联系起来),Person类我们已经有了,这样最终我们要添加一个包含Welfare的Duty类. 

3.设计

我们来看客户的话:"按照人们不同的职位,给与不同的福利,一个人可能身兼几个职位",也就是说我们的Person可能要维护一个职位的列表,然后把它们的福利加起来最后生成员工的最终福利.这样设计是可以完成用户的需求,可是当职位发生变的时候,或者职位需要去添加一些比如权限之类的操作,这样就不是简单的叠加问题了,而且当用户说我们公司现在不要福利了,那么我们的Person类就要修改(当然我们也不能去派生Person的子类,因为职位何其多,这样做子类的数目是不可想象的).我们的目的就是让系统更长寿,避免修改,所以我们要采取其他的方式来设计.总结一下我们的设计意图:要不修改原有类,给这个类去添加一些方法,而且可以无限的去添加.并且不能通过派生子类来实现人员的职位.什么模式与之匹配呢??

 

GOF23中的Decorator(装饰):在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责.

 

4.类图

 

 

 

Duty这个类层次是新加的,AbstractPerson和他的两个子类Staff和InterShip是第一篇中设计完成的.

 

在这里Person,没有任何改动.相关代码请察看第一篇.

 

我们来看看Duty的类层次的代码:

 

 

ContractedBlock.gif ExpandedBlockStart.gif Code
public abstract class Duty : AbstractPerson  //Is-a 的关系
{
    
protected AbstractPerson _person; //Has-a的关系
    protected string _dutyName;

    
public Duty(AbstractPerson person)  //将客户代码传来的Person,重新装饰,成为新的Person
    { 
        
this._person=person;
        
this._personName = person.PersonName;
        
this._personSalary = person.PersonSalary;
    }

    
public string DutyName
    {
        
get{return _dutyName;}
        
set{_dutyName=value;}
    }

    
public abstract double GetWelfare();//GetWelfare方法为抽象方法,留给子类实现
}

public class BaseDuty : Duty  //员工基本福利
{
    
public BaseDuty(AbstractPerson person)
        : 
base(person)
    { 
    }
    
public override double GetWelfare()
    {
        Duty duty 
= _person as Duty;
        
if (!Equals(duty, null))  //如果Person是已经被装饰过的,则将原有的福利进行装饰
        {
            
return 200 + duty.GetWelfare();
        }
        
return 200;//午餐费
    }
    
public override double GetShouldpaid(IPrize prize)
    {
        
return _person.GetShouldpaid(prize);
    }
}

public class TeamLeader:Duty   //组长的福利
{
    
public TeamLeader(AbstractPerson person)
        : 
base(person)
    { 
    }
    
public override double GetWelfare()
    {
        Duty duty 
= _person as Duty;
        
if (!Equals(duty, null))
        {
            
return 500 + duty.GetWelfare();
        }
        
return 500;//话补
    }
    
public override double GetShouldpaid(IPrize prize)
    {
        
return _person.GetShouldpaid(prize);
    }
}

public class DepartmentManager:Duty  //部门经理的福利
{
    
public DepartmentManager(AbstractPerson person)
        : 
base(person)
    { 
    }
    
public override double GetWelfare()
    {
        Duty duty 
= _person as Duty;
        
if (!Equals(duty, null))
        {
            
return 1000 + duty.GetWelfare();
        }
        
return 1000;//车补
    }
    
public override double GetShouldpaid(IPrize prize)
    {
       
return  _person.GetShouldpaid(prize);
    }
}

 

Duty继承了Person,那么就是说在装饰一个Person后他还是一个Person,这很合理,而且可以无限添加。

 

 调用程序:

 

 

ContractedBlock.gif ExpandedBlockStart.gif Code
   class Program
    {
        
static void Main(string[] args)
        {
            Staff staff 
= new Staff();
            staff.PersonName
="涵舍愚人";
            BaseDuty bd 
= new BaseDuty(staff);
            TeamLeader tl 
= new TeamLeader(bd);
            DepartmentManager dm 
= new DepartmentManager(tl);
            Console.Write(dm.PersonName
+"本月赢得工资="+dm.GetShouldpaid(BadPrize.badPrize)+"     应发福利="+ dm.GetWelfare());

            Console.Read();
        }
    }

 

 

输出结果:

 

 

 

 

 

这样我们就完成了不修改Person,而给人员添加了职位,这个职位可以无限的加,你可以自己成立一个公司,公司就你一个人,去担当所有的职位。。呵呵

 

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

转载于:https://www.cnblogs.com/xugao918/archive/2008/08/12/1265805.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值