Fork me on GitHub

好的设计产生灵活的软件-上(good design = flexible software part 1)

------------没有什么是一成不变的nothing ever stays the same

 

 

 引言

  变化是不可避免的。无论现在你多么喜欢你的软件,明天还是可能会改变。你把软件开发的越难以改变,相应用户的需求变更就越困难。在本篇中我们将会视图改进一个已有的系统,看看多么小的一个改变能导致大问题。

 正文

      先来看一个已有系统的类关系图。就是一个guitar销售商店,可以查询guitar,添加guitar。

      客户说最近他想卖mandolins曼陀林(一种琵琶类乐器),想要我们在系统中实现这个功能,并且可以针对这种乐器进行搜索。

      我们需要在原有系统中支持曼陀林这种新的乐器。既然是乐器,肯定和guitar有共同的地方,我们可以抽象出来。加入一个乐器类,表示曼陀林和guitar的抽象。

 

 

     

      其实在上图中,我们会发现,乐器的细节类和guitar的细节类,以及mandolin的细节类都很相似,还应该有个抽象的乐器细节类。把共同的细节信息都移到抽象类中。

      就会变成下面的结果

 

 

 

 

 

      在UML图中

      如上图所示,第一条是关系,也就是通常我们说的类之间的关系,1:1,1:n,n:1,之类的。第二条就是继承。第三条是集成,还不太理解,在后面理解了我们再来讨论他。

      由上面最后的两张类图,我们可以写出下面的代码。

 

代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BeautyCode.Common.ConApp.Head.First.OO.Design
{
    
public abstract class InstrumentSpec
    {
        
private Builder _builder;
        
private InstrumentType _type;
        
private Wood _backwood;
        
private Wood _topwood;
        
public InstrumentSpec(Builder builder, InstrumentType type, Wood backwood, Wood topwood)
        {
            _builder 
= builder;
            _topwood 
= topwood;
            _type 
= type;
            _backwood 
= backwood;
        }
        
public virtual  bool Matches(InstrumentSpec instance)
        {
            
if (instance._builder != _builder)
                
return false;
            
if (instance._backwood != _backwood)
                
return false;
            
if (instance._topwood != _topwood)
                
return false;
            
if (instance._type != _type)
                
return false;
            
return true;

        }
    }
    
public abstract class Instrument
    {
        
private string _serialNumber;

        
public string SerialNumber
        {
            
get { return _serialNumber; }
        }
        
private double _price;

        
public double Price
        {
            
get { return _price; }
        }
        
private InstrumentSpec _spec;

        
public InstrumentSpec Spec
        {
            
get { return _spec; }
        }
        
public Instrument(string serialNumber, double price, InstrumentSpec spec)
        {
            _serialNumber 
= serialNumber;
            _price 
= price;
            _spec 
= spec;
        }

    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BeautyCode.Common.ConApp.Head.First.OO.Design
{
    
public class GuitarSpec : InstrumentSpec
    {
        
private int _numString;

        
public int NumString
        {
            
get { return _numString; }

        }
        
public GuitarSpec(Builder builder, InstrumentType type, Wood backwood, Wood topwood, int numString)
            : 
base(builder,
                type, backwood, topwood)
        {
            
this._numString = numString;
        }
        
public override bool Matches(InstrumentSpec instance)
        {
            
if (!base.Matches(instance))
                
return false;
            
if (!(instance is GuitarSpec))
                
return false;
            GuitarSpec spec 
= instance as GuitarSpec;
            
if (spec._numString != _numString)
                
return false;
            
return true;
        }
    }

    
public class Guitar : Instrument
    {
        
public Guitar(string serialNumber, double price, GuitarSpec spec)
            : 
base(serialNumber, price, spec)
        {
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BeautyCode.Common.ConApp.Head.First.OO.Design
{
    
public class MandolinSpec : InstrumentSpec
    {
        
private Style _style;

        
public Style Style
        {
            
get { return _style; }
        }
        
public MandolinSpec(Builder builder, InstrumentType type, Wood backwood, Wood topwood, Style style)
            : 
base(builder,
                type, backwood, topwood)
        {
            
this._style = style;
        }
        
public override bool Matches(InstrumentSpec instance)
        {
            
if (!base.Matches(instance))
                
return false;
            
if (!(instance is GuitarSpec))
                
return false;
            MandolinSpec  spec 
= instance as MandolinSpec ;
            
if (spec._style  != _style )
                
return false;
            
return true;
        }
    }
    
public class Mandolin : Instrument
    {
        
public Mandolin(string serialNumber, double price, MandolinSpec spec)
            : 
base(serialNumber, price, spec)
        {
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BeautyCode.Common.ConApp.Head.First.OO.Design
{
    
public class Inventory
    {
        
private List<Instrument> _inventory;
        
public Inventory()
        {
            _inventory 
= new List<Instrument>();
        }
        
public void AddInstrument(string serialNumber,double price,InstrumentSpec spec)
        {
            Instrument instance 
= null;
            
if (spec is GuitarSpec)
            {
                instance 
= new Guitar(serialNumber, price,(GuitarSpec ) spec);
            }
            
else if (spec is MandolinSpec)
            {
                instance 
= new Mandolin(serialNumber, price, (MandolinSpec)spec);
            }
            _inventory.Add(instance);
        }
        
public Instrument Get(string serialNumber)
        {
            
return _inventory.Find(i => i.SerialNumber == serialNumber);
        }
        
public List<Instrument> Search(MandolinSpec searchSpec)
        {
            List
<Instrument> instances =  _inventory  .FindAll(i => i.Spec.Equals(searchSpec));
            
return instances;
        }
    }
}

 

 

     

 结论

     

【Blog】http://virusswb.cnblogs.com/

【MSN】jorden008@hotmail.com

【说明】转载请标明出处,谢谢

posted on 2010-07-24 20:39  HackerVirus  阅读(211)  评论(0编辑  收藏  举报