在前三篇中我们设计了员工的工资,绩效将金,以及员工福利,使用了Bridge(员工和工资的组合),Stratege(工资和绩效将金的设计)以及(Singleton)单件了这些算法,然后用Decorator(装饰)将员工进行职位的装饰.这些设计在我们前面所说的场景下,是符合设计模式的意图的,但是它仍然有一些漏洞.

我们来看看我们的员工类的代码,注意注释的文字.

 

 

 AbstractPerson
     {
            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(IPrize prize);  //在这里把员工类和奖金类耦合了
     }

    
public  class Staff : AbstractPerson
     {
        
public override double GetShouldpaid(IPrize prize)
        {
            _personSalary 
= new StaffSalaryFactory().GetSalary();  //在这里对Salary进行了初始化,使得我们没有办法在初始化Person的时候对工资进行多态.
            _personSalary.Salaryprize = prize;
            
return _personSalary.GetShouldpaid();
        }
     }
   

 

 上面的设计使得Person和Iprize耦合,而且Person与Salary的结合也不是很灵活,怎么去解决这个问题呢.

 

先来解决Person和Salary: Person和Salary使用了Bridge模式,该模式的做到了两个类系列的独立变化.那么我们就要有种方式去生成这两个系列.

AbstractFactory(抽象工厂):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

ok,这个模式适合我们的设计意图.第二篇里面我们用了工厂方法来创建工资,同样我们也可以用它来创建Person.这样Person发生了变化,并不会影响到我们的抽象工厂.(回忆一下第二篇中工厂方法的意图)下面我们来看看代码:

 

 

工资的工厂方法:

 

 SalaryFactory
    {
        public abstract Salary GetSalary();  //留给具体某种工资福利制度工厂去实现
    }
    
public class StaffSalaryFactory : SalaryFactory
    {
        
public override Salary GetSalary()  //具体某种工资福利制度工厂
        {
            
return new SttafSalary();
        }
    }
    
public class InternshipSalaryFactory : SalaryFactory
    {
        
public override Salary GetSalary()  //具体某种工资福利制度工厂
        {
            
return new InternshipSalary();
        }
    }

 

 

员工的工厂方法:

 

 PersonFactory
    {
        public abstract AbstractPerson GetPerson();  //留给具体某种工资福利制度工厂去实现
    }
    
public class StaffFactory : PersonFactory
    {
        
public override AbstractPerson GetPerson()  //具体某种工资福利制度工厂
        {
            
return new Staff();
        }
    }
    
public class InternshipFactory : PersonFactory
    {
        
public override AbstractPerson GetPerson()  //具体某种工资福利制度工厂
        {
            
return new Internship();
        }
    }

 

生成员工和工资的抽象工厂:

 

 

    {
        AbstractPerson GetPerson();  //创建员工对象
        Salary GetSalary();//创建工资对象
    }
    
public class StaffAndSalaryFactory
    {
        
public AbstractPerson GetPerson()
        {
            
return new StaffFactory().GetPerson();  //通过工厂方法创建正式员工
        }
        
public Salary GetSalary()
        {
            
return new StaffSalaryFactory().GetSalary(); //通过工厂方法创建正式员工的工资
        }
    }
    
public class InternshipAndSalaryFactory
    {
        
public AbstractPerson GetPerson()
        {
            
return new InternshipFactory().GetPerson(); //通过工厂方法创建实习员工
        }
        
public Salary GetSalary()
        {
            
return new InternshipSalaryFactory().GetSalary(); //通过工厂方法创建实习员工的工资
        }
    }

 

 

好了,解决了Person和Salary的创建问题,我们来看看Person和Iprize的依赖问题. Iprize属于工资的一部分,那么他的创建和依赖应该在Salary这个类,而且我们已经单件了Iprize的子类.并且上面我们解决了Person里创建Salary的问题,所以我们将Person类,修改成如下:

 

 

Person类:

 

 

 AbstractPerson 
{
    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();
    }
}

 

 

 

 还有我们原有的Duty类的代码(他是不需要修改的):

 

{
    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()
    {
        
return _person.GetShouldpaid();
    }
}

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()
    {
        
return _person.GetShouldpaid();
    }
}

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()
    {
       
return  _person.GetShouldpaid();
    }
}

 

 

调用程序:

 

 

 

 Program
    {
        static void Main(string[] args)
        {
            StaffAndSalaryFactory saf 
= new StaffAndSalaryFactory();  //实例化抽象工厂

            AbstractPerson staff 
= saf.GetPerson();  //创建员工
            staff.PersonName = "涵舍愚人";

            staff.PersonSalary 
= saf.GetSalary();//创建员工工资

            staff.PersonSalary.Salaryprize 
= BadPrize.badPrize;//使用单件初始化员工工资的绩效部分
     
            TeamLeader tl 
= new TeamLeader(staff);//给员工组长的职务

            DepartmentManager dm 
= new DepartmentManager(tl); //员工还是部门经理

            Console.Write(dm.PersonName
+"本月赢得工资="+dm.GetShouldpaid()+"     应发福利="+ dm.GetWelfare());
            Console.Read();
        }

 

 

 输出结果:

 

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

 

这样我们就用抽象工厂把Person与Salary的紧耦合给解耦了,如果工资的需求变更了Staff中的Salary可以是任何的Salary子类,并不会影响到Person.

这里要说明一下,工厂方法和抽象工厂通常用单件形式,因为这两个工厂模式的职责是创建对象,所以工厂有一个就足够了,因第二篇使用了单件,这里不在赘述,只要记得工厂通常是单件就好.

 

(关于工厂方法和抽象工厂的区别:工厂方法创建一个产品,而抽象工厂创建一系列的产品)

 

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

相关文章: