学习设计模式也有一段时间了,但此次却是第一次将设计模式运用到实际开发中,可能此文设计内容过于简单,但毕竟是一次尝试。发到首页只希望与各位交流,如有不足,请多指教...谢谢~   

     缘由    
 一直在开发一个控制产品入库和出货的系统,基本的业务流程是这样的:首先开立产品入库联络单,然后仓库会根据此单据到进行产品实物入库,待确认数量,料号无误后,此信息要抛转ERP系统中,以作账务控制...(其中更多作业细节从略)
     对于此需求,我简单的就依过程化的方式进行了实现:
     封装一个作业类,控制入库抛转动作:

 CellGoodsRec
    {
        private string bill_no;

        public string Bill_no
        {
            
get { return bill_no; }
            
set { bill_no = value; }
        }
       

       public string ExecuteReceive()
       {
           
//在这里进行入库作业
       }

    }

 Client:

 btnGoodsRec()
        {
            CellGoodsRec rec = new CellGoodsRec();
            rec.ExecuteReceive();
        }

     需求变化
     随着开发接近尾声,用户突然提出一个问题:原来的做法只能适用于半成品的入库,而成品的入库作业方式稍有不同,系统应该能应对这两种情况...
     按道理说,最简单的做法,无非就是再加上一个成品入库的方法到封装的类中而已。

     敏捷思想
     但是依照敏捷开发的思想,当我们在做需求变更的时候,要考虑到将来可能发生的新的需求,而我们此时的设计应该能够轻松应对将来的需求变更...(不知道理解的是否正确)。也就是说,现在用户提出系统要适应半成品,成品的入库作业,将来是否可能有原材料入库的可能呢?到那时该如何应对?再加一个方法吗?     
     依据OO设计原则,一个类只能有一种引起它变化的原因(单一职责原则),而上述应对变化的做法无疑违背了这个原则.(成品,半成品,原材料任何一种入库方式发生变化,此类就要重新编译)。
     此时该是设计模式入场的时候了,【封装变化点】用在这里恰到好处。注意到,不管哪种情况,终究都属于入库范畴,只是方式不同而已,那么此时可能把入库的动作进行抽象封装,而具体到每种情况对此抽象完成具体实现,从而实现职能分配均匀,职责单一。而在客户端我们则可以根据具体情况,实例化不同的实现即可。
     
     运用简单工厂模式进行第一个重构
     抽象类:

 GoodsReceive
    {
        private string workorder;

        public string Workorder
        {
            
get { return workorder; }
            
set { workorder = value; }
        }

        private string bill_no;

        public string Bill_no
        {
            
get { return bill_no; }
            
set { bill_no = value; }
        }
       
       
public abstract string ExecuteReceive();

    }

     半成品具体类:

 CellGoodsRec:GoodsReceive
    {
        public override string ExecuteReceive()
        {
            
string returninfor =Bill_no;

            //在这里进行半成品入库作业:依据入库单号进行
           
            
return returninfor;
        }
    }

      成品具体类:

 ModGoodsRec:GoodsReceive
    {

        public override string ExecuteReceive()
        {
            
//code here
            string TransNo =Workorder;

            ////在这里进行成品入库作业:依据工单号码进行

            
return TransNo;
        }
    }

     简单工厂:

 DBFactory
    {
       
        public static GoodsReceive GetRecType(ReceiveType RecType)
        {
            GoodsReceive GoodsRec 
= null; ;

            switch (RecType)
            {
                
case ReceiveType.CELL:
                    GoodsRec 
= new CellGoodsRec();
                    
break;
                
case ReceiveType.MOD:
                    GoodsRec 
= new ModGoodsRec();
                    
break;
            }
            
return GoodsRec;
        }
    }

     为了作业方便,添加了枚举,ReceiveType

 ReceiveType
    {
       CELL,   //半成品
        MOD     //成品
    }

     Client:
     

 sender, EventArgs e)
        {
            GoodsReceive execRFC = DBFactory.GetRecType(ReceiveType.CELL);

            execRFC.Bill_no = "BN101";   //传递入库单号

            
string TranferNo = execRFC.ExecuteReceive();

            MessageBox.Show(TranferNo);
        }

        //成品作业
        private void btnModRec_Click(object sender, EventArgs e)
        {
            GoodsReceive execRFC 
= DBFactory.GetRecType(ReceiveType.MOD);

            execRFC.Workorder = "WO001";   //传递工单号码

            
string TranferNo = execRFC.ExecuteReceive();

            MessageBox.Show(TranferNo);
        }

      待续......