[设计模式]简单工厂(Simply Factory)

简单工厂Simple Factory

 

时常能在大几百行甚至几千行的类代码中看到如下代码的身影:

    class AnimalShow
    {
        //根据不同的动物名称显示对应的动物
        public void DisplayAnimal(String animalName)
        {
            Animal animal;

            if(animalName == "dog")
            {
                animal = new Dog();
            }
            if (animalName == "cat")
            {
                animal = new Cat();
            }

            animal.display();
        }
    }

  

高级一点的会用上枚举,可能会写成这样:

    class Navigator
    {
        enum userType { visitor, user, vip };

        //根据不同的用户身份,导航到相应的页面
        public void Navigation(userType currentUser)
        {
            String targetURL = "";

            switch(currentUser)
            {
                case userType.visitor:
                    targetURL = "/visitor.html";//这里其实相当于是一次获取String的实例的操作;等价于targetURL = new String("/visitor.html");
                    break;

                case userType.user:
                    targetURL = "/user.html";
                    break;

                case userType.vip:
                    targetURL = "/vip.html";
                    break;
            }

            NavigateTo(targetURL);//导航到相应的页面
        }
    }

 

  我们都知道,在实际的开发中,唯一不变的就是变化!

 

  特别是第一段程序中的if{}部分,还有第二段程序中的switch{}部分,都是三天两头就有可能被要求修改的。而实际的项目中,像这样的主体类可能会有成百上千行代码,这些if/switch到时只会被淹没在代码海中,每次修改都要在茫茫码海中找到它们,并且再作出修改,这种事情做多了久而久之很消人志气。

  还有一点非常值得注意——这样的代码一点都不适合复用,直接就在主体类中进行硬绑定显然对今后的修改非常不利。

 

  解决的办法可以利用简单工厂模式,使类和类之间解耦

 

  以第二个例子哪来开刀。将容易改变的switch{}部分提取出来,构建成一个生产实例的工厂 —— 即用户丢入需求,工厂则依照用户的需求返回相应的实例。

  运用简单工厂修改后的代码如下:

  1.工厂类:

    //URL工厂,专门负责生产各种工厂实例       
    class URLFactory
    {
        //根据不同的用户需求返回不同的URL实例
        public String GetURL(userType currentUser)
        {

            String targetURL = "";

            switch (currentUser)
            {
                case userType.visitor:
                    targetURL = "/visitor.html";
                    break;

                case userType.user:
                    targetURL = "/user.html";
                    break;

                case userType.vip:
                    targetURL = "/vip.html";
                    break;
            }

            return targetURL;
        }
    }

  2.主体类:

    class Navigator
    {
        enum userType { visitor, user, vip };

        public void Navigation(userType currentUser)
        {
            URLFactory urlFactory = new URLFactory();

            String targetURL = urlFactory.GetURL(currentUser);

            NavigateTo(targetURL);
        }
    }

  也许有人要说了,我原来好端端地一个类,你楞要拆成两个,这不是增加了代码维护的难度么?

  表面上看起来好像是这样,其实不然,这多出的一个类使得原先的主体类变得更加的清楚,增加了代码的可读性,而且将所有容易改变的部分都提取出来之后(此例中只有获取URL这个地方容易改变),这就使得今后对代码的维护只要对这几个类进行就好了,代码少、逻辑清晰,实在是方便修改。

  而且更重要的是,这样一来,这个根据用户不同身份而取得不同URL的方法将变得可以复用。

  这其实又涉及到设计模式的另外一个重要思想——“依赖倒置

//to be continued.

posted @ 2012-06-23 23:48  叫我学徒  阅读(224)  评论(0编辑  收藏  举报