• 如何使用设计模式来构造系统(1) 四


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

     

      一直很想写关于设计模式的具体使用的文章,可是一直没想好怎么去写,才可以通俗易懂,真正的让设计模式,应用到系统设计中.今天终于想到了,这个系列准备用实例去讲解如何使用(GOF)设计模式.

         准备用公司的人员管理系统来做这个实例,为什么选他呢?我觉得大家基本上都是公司员工,对这方面会比较熟悉.OK我们现在来定义这个系统.

    客户A说:我们的系统要管理人员的工资.(为了模拟真实的开发场景,这里暂时先定义一个功能)人员分为实习员工和正式员工,他们的基本工资是不同的,工资包括基本工资和绩效工资.

     

    1.分析

    好,那我们现在就来分析这个系统吧,如何分析呢.大家都知道在面向对象分析中,比较难的是如何划分和定义一个类,  这里给大家介绍一个方法,"名词分析法",也就是用名词来划分你的类.举个例子:上面客户A说:"我们的系统要管理人员的工资",当然这里"我们"和"系统"这两个名词没有什么意义,就不去管它们了,我们来看接下来的"人员的工资",这里出现了人员和工资,那么我们就把他们定义成两个类Person和Salary.下面的需求:"人员分为实习员工和正式员工",那么就有实习员工和正式员工两个类,还有基本工资和绩效工资.

     

    2.过滤

    好,我们通过分析得到了 Person,InternshipSalary(实习员工),SttafSalary(正式员工),后两者也属于员工,那么我们只需要定义person,然后衍生出实习员工和正式员工,就可以了.

    Salary,基本工资,绩效工资:由于绩效工资和公司的制度关系很密切,变化可能会很频繁,而使用设计模式的目的就是封装变化,使得代码更好的复用,所以我们要把绩效工资和Salary分开,单独封装,而基本工资就是一个数,所以直接作为Salary的一个属性就可以了.

     

    3.设计

    我们来看客户的话:"人员分为实习员工和正式员工,他们的基本工资是不同的,工资包括基本工资和绩效工资."

    在这里Person应该包含Salary这个类,但是Person和Salary都有2种分类,而且客户很有可能再添加新的分类,那么我们如何来避免这种需求改变而带来的修改呢??

    GOF23中的Bridge(桥接),就可以完成这个设计.我们来看下Bridge这种设计模式的意图:将抽象部分与他的实现部分分离,使他们都可以独立的变化.和我们的意图相符合.

     

    我们知道工资中包含绩效工资,而绩效工资实际上就是一个算法,(在这里我们先不讨论怎么去评判一个人的绩效),完成多少的人给多少的绩效工资.每个人每月的绩效都不一样,可能根据很多情况发生变化.怎么来设计呢?

    GOF23中的Strategy(策略):定义一系列算法,使他们可以互相替换.独立于客户代码而变换.就是他了,嘿嘿!!

     

    4.类图

     

     

    嘿嘿,可能大家已经看出来Bridge模式和Stratege模式很像了吧,其实他们的类图确实是一样的,从不太严格的角度来说:可以认为他们是一种实现方式,但是他们的意图不一样,Bridge更多的是类与类之间的关系,而Stratege是类与行为之间的关系,也就是说Bridge是对某一个类的一系列可变的封装,而Stratege则是对某一种可变的算法的封装。

     

    2.代码:

     

    绩效奖金的实现:


     public interface IPrize
        {
            
    double GetPrize(Salary salary);
        }
        
    public class BadPrize : IPrize //绩效不好的奖金比率
        {
        
            
    public double GetPrize(Salary salary)
            {
                
    return salary.SalaryNum * 0.5;  //干的不好奖金扣一半
            }
        }

        
    public class GoodPrize : IPrize  //绩效好的奖金比率
        {
            
    public double GetPrize(Salary salary)
            {
                
    return salary.SalaryNum * 1;  //干的好奖金全发,哈哈
            }
        }

     

     工资的实现:


      public abstract class Salary
        {
            
    protected double _salaryNum; //工资基数
            protected IPrize _salaryprize;  //这里维护一个绩效奖金的引用。

            
    public double SalaryNum  
            {
                
    get { return _salaryNum; }
                
    set { _salaryNum = value; }
            }

            
    public IPrize Salaryprize
            {
                
    get { return _salaryprize; }
                
    set { _salaryprize = value; }
            }

            
    public abstract double GetShouldpaid();  //留给具体某种工资福利制度去实现
        }

        
    public class InternshipSalary : Salary  //实习者的应得工资
        {
            
    public override double GetShouldpaid()
            {
                _salaryNum 
    = 3000;//实习者的工资基数
                return _salaryNum + _salaryprize.GetPrize(this);
            }
        }

        
    public class SttafSalary : Salary //员工的应得工资
        {
            
    public override double GetShouldpaid()
            {
                _salaryNum 
    = 6000;//正式员工的工资基数
                return _salaryNum + _salaryprize.GetPrize(this);
            }
        }

     

    员工的实现:

     


        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 SttafSalary(); //初始化正式员工的基本工资
                _personSalary.Salaryprize = prize; //赋予绩效
                return _personSalary.GetShouldpaid();
            }
         }
        
    public class Internship : AbstractPerson
        {
            
    public override double GetShouldpaid(IPrize prize)
            {
                _personSalary 
    = new InternshipSalary();//初始化实习员工的基本工资
                _personSalary.Salaryprize = prize;//赋予绩效
                return _personSalary.GetShouldpaid();
            }
        }

     

     调用程序:

     


       class Program
        {
            
    static void Main(string[] args)
            {
                Staff staff 
    = new Staff();
                
                staff.PersonName
    ="涵舍愚人";
                Console.Write(staff.PersonName
    +"本月实发工资为"+staff.GetShouldpaid(new GoodPrize()));
                Console.Read();
            }
        }

     

    输出结果:

     

     

    我们使用了两种设计模式Bridge和Strategy ,来封装了员工和工资,以及工资和绩效的变化,好了这样我们就设计完成了用户的需求,但是就上面的设计,还是有很多漏洞的,下一篇我们将继续用模式优化这些设计.

  • 相关阅读:
    小米范工具系列之一:小米范 web查找器
    不同格式的ip 统一转成ip列表
    Educational Codeforces Round 32
    离散化方式
    线段树合并与分裂
    HDU1074
    容斥原理
    模板
    HDU1024 Max Sum Plus Plus
    CSA Round #56
  • 原文地址:https://www.cnblogs.com/sier/p/5676524.html
Copyright © 2020-2023  润新知