设计模式是工具,而不是目标

在我职业生涯的早期,我曾认为设计模式就是软件开发的全部。我所有的系统设计都是从选择一个合适的设计模式开始的:工厂模式、仓储模式、单例模式等等,但是后来我发现这样的系统很难维护,更难以与同事交流。事实上,我并没有正确理解设计模式的用处。

五年之后,研究设计模式已经成了我的日常工作,目标是论证这些模式在C#.NET环境下是如何帮助我们维护项目的。我建立并记录了一些模式的例子,包括适配器模式、外观模式、抽象工厂模式等。这些对我来说很有意义,让我更加深入地理解了这些设计模式,但仍然有些问题看起来有点古怪。

我得讲清楚,我从未读过那本Gang of Four book(注:即《设计模式:可复用面向对象软件的基础》,这本书中定义了大部分模式,由四人合著,故有此别称),也许我的问题可以在那里找到解答。事实上,我对这些模式的所有认识都来自网上的资源,比如Do Factory这样的地方。但我越了解他们,我越相信设计模式不是我们应该努力追求的目标。

以适配器模式为例,适配器将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。假如现在我们一个这样的API(来自Do Factory:http://www.dofactory.com/net/adapter-design-pattern ):

class Compound  
{
    protected string _chemical;
    protected float _boilingPoint;
    protected float _meltingPoint;
    protected double _molecularWeight;
    protected string _molecularFormula;

    // Constructor
    public Compound(string chemical)
    {
        this._chemical = chemical;
    }

    public virtual void Display()
    {
        Console.WriteLine("\nCompound: {0} ------ ", _chemical);
    }
}

class ChemicalDatabank  
{
    // The databank 'legacy API'
    public float GetCriticalPoint(string compound, string point)
    {
        // Melting Point
        if (point == "M")
        {
            switch (compound.ToLower())
            {
                case "water": return 0.0f;
                case "benzene": return 5.5f;
                case "ethanol": return -114.1f;
                default: return 0f;
            }
        }
        // Boiling Point
        else
        {
            switch (compound.ToLower())
            {
                case "water": return 100.0f;
                case "benzene": return 80.1f;
                case "ethanol": return 78.3f;
                default: return 0f;
            }
        }
    }

    public string GetMolecularStructure(string compound)
    {
        switch (compound.ToLower())
        {
            case "water": return "H20";
            case "benzene": return "C6H6";
            case "ethanol": return "C2H5OH";
            default: return "";
        }
    }

    public double GetMolecularWeight(string compound)
    {
        switch (compound.ToLower())
        {
            case "water": return 18.015;
            case "benzene": return 78.1134;
            case "ethanol": return 46.0688;
            default: return 0d;
        }
    }
}

但是现在,我们的新系统希望一个叫做RichCompound的对象能够调用Critical Point, Molecular Weight 和 Molecular Structure,而不是查询API,这时候适配器模式告诉我们应该这样做:

class RichCompound : Compound  
{
    private ChemicalDatabank _bank;

    // Constructor
    public RichCompound(string name)
        : base(name)
    {
    }

    public override void Display()
    {
        // The Adaptee
        _bank = new ChemicalDatabank();

        _boilingPoint = _bank.GetCriticalPoint(_chemical, "B");
        _meltingPoint = _bank.GetCriticalPoint(_chemical, "M");
        _molecularWeight = _bank.GetMolecularWeight(_chemical);
        _molecularFormula = _bank.GetMolecularStructure(_chemical);

        base.Display();
        Console.WriteLine(" Formula: {0}", _molecularFormula);
        Console.WriteLine(" Weight : {0}", _molecularWeight);
        Console.WriteLine(" Melting Pt: {0}", _meltingPoint);
        Console.WriteLine(" Boiling Pt: {0}", _boilingPoint);
    }
}

这样,RichCompound类就成为先前API的一个适配器了:它将将查询转换成对API的调用。这样,既达到了新系统的要求又不需要重写API。

这就是我想说的关于设计模式的问题:它们是应当出现而不是特意出现的。我们的代码不应当以符合设计模式为目标,但我们应该知道他们是什么,当我们不小心创建一个时,我们可以更好地把它描述给别人。

换句话说,如果你发现自己在写代码之前就在想,“我知道,我会用一个设计模式”,你就做错了。

在系统初步设计阶段,设计模式应当是不起作用。在这个阶段,你唯一应该考虑的是如何正确地实现产品要求。在这之后,您可以创建一个“正确”的架构:合适的业务、客户、代码标准。在这个阶段,设计模式起不到应有的作用,反而人为地限制了代码的功能。如果你的脑中全是适配器模式,你就很难相处一个或许更适合你的项目但是连名字都没有的模式。

我认为设计模式是重构和沟通的工具。通过学习它们是什么它们是用来干嘛的,我们可以更迅速地重构棘手的项目、更深入地理解不熟悉的项目。如果我们在项目中看到了一些,比如复合模式,我们可以寻找这个模式独立的片段(树结构,树叶和树枝,共同类),更快速地认识为什么这种结构会被使用,识别模式有助于你发现为什么代码会以这种结构组织。

当然,如果模式运用不恰当,这一模式反而会适得其反。如果有人在本不需要使用单例模式的地方使用了它,我们可能就会在那被卡住。因此,在开始设计一个项目时,先不要想着使用固有的模式,当你对代码的全局架构有了大致的构想之后,再使用它,并且用在真正有意义的地方。在无意义地地方使用模式就是项目不可维护的元凶之一。

设计模式是工具,不是目标。真正需要的时候再用它,而不是一开始就被它禁锢。

关于 “设计模式是工具,而不是目标” 的 1 个意见

  1. I think other web-site proprietors should take this website as an model, very clean and excellent user friendly style and design, as well as the content. You are an expert in this topic!

评论关闭。