在前三篇中我们设计了员工的工资,绩效将金,以及员工福利,使用了Bridge(员工和工资的组合),Stratege(工资和绩效将金的设计)以及(Singleton)单件了这些算法,然后用Decorator(装饰)将员工进行职位的装饰.这些设计在我们前面所说的场景下,是符合设计模式的意图的,但是它仍然有一些漏洞.
在前三篇中我们设计了员工的工资,绩效将金,以及员工福利,使用了Bridge(员工和工资的组合),Stratege(工资和绩效将金的设计)以及(Singleton)单件了这些算法,然后用Decorator(装饰)将员工进行职位的装饰.这些设计在我们前面所说的场景下,是符合设计模式的意图的,但是它仍然有一些漏洞.
我们来看看我们的员工类的代码,注意注释的文字.
Code
public abstract class 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发生了变化,并不会影响到我们的抽象工厂.(回忆一下第二篇中工厂方法的意图)下面我们来看看代码:
工资的工厂方法:
Code
public abstract class 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();
}
}
员工的工厂方法:
Code
public abstract class 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();
}
}
生成员工和工资的抽象工厂:
Code
public interface IPersonAndSalaryFactory //抽象工厂,用来创建人员和工资这两个系列
{
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类:
Code
public abstract class 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类的代码(他是不需要修改的):
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()
{
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();
}
}
调用程序:
Code
class 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();
}
输出结果:
这样我们就用抽象工厂把Person与Salary的紧耦合给解耦了,如果工资的需求变更了Staff中的Salary可以是任何的Salary子类,并不会影响到Person.
这里要说明一下,工厂方法和抽象工厂通常用单件形式,因为这两个工厂模式的职责是创建对象,所以工厂有一个就足够了,因第二篇使用了单件,这里不在赘述,只要记得工厂通常是单件就好.
(关于工厂方法和抽象工厂的区别:工厂方法创建一个产品,而抽象工厂创建一系列的产品)
下一篇:如何使用设计模式来构造系统--(5)