设计模式 -- 工厂方法

理解了简单工厂就不难理解工厂方法,工厂方法没有了“工厂”这个类,它是用抽象方法实现的,这就涉及到了“多态”。子类实现父类的抽象方法,也就是把“生产对象”这个职责从工厂中拿出来让具体类来实现。

举个例子来说吧,有一个Pizza店,它有很多子类,有纽约风味的Pizza店,还有芝加哥风味的Piiza店,不同的Pizza店有cheesePizza,ClamPizza,VeggiesPizza,PepperoniPizza四种不同口味的Piiza.我们知道不同的风味的店在你不同的地区,而且一个风味的Pizza店只能点这中风味的Piiza。如果要用简单工厂来实现这个例子,那么在简单工厂的createPizza(参数)的参数中我们至少要传进来“风味”和“口味”两个不同的参数,这样就会使得Pizza的“口味”和“风味”严重的依赖,而且我们已经说了,一个风味的Pizza店只能点这中风味的Piiza,所以看到了,用简单工厂来实现这个例子是不理想的。那么我们看看“工厂方法”。

1、什么是“工厂方法”?

    工厂方法是一个抽象类的抽象方法。它定义了一个创建对象的接口,但是由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

2、“工厂方法”如何实现?

    还以上面的例子说明,在Pizza店里点Pizza的时候会说明是什么口味的,这个时候,如果你在纽约的Pizza店里,那么给你呈上来的就是纽约风味中这个口味的,如果你是在芝加哥呢,那么你将享用芝加哥风味中这个口味的。所以我们看到了,我们得有两个风味的Pizza店(纽约风味店和芝加哥风味店),然后每个店实现继承自Piiza店的createPizza(参数)的方法,这样每个店就能按照自己的风味来制作不同的口味的Pizza了。那么你在吃Pizza前就得选择好要哪个风味的,根据你的选择我们选择不同的风味店。看看这个类图吧:

3、示例代码

public abstract class PizzaStore
    {
        /*
         * 从工厂类中把建造对象的方法拿出来,让具体的类来实现,
         * 这就是工厂方法,工厂方法用来处理对象的创建,并将这样的
         * 行为封装在子类中,这样,客户程序中,关于超类代码和子类
         * 对象创建代码解耦了
         */
        public abstract Pizza createPizza(string type);

        public Pizza orderPizza(string type)
        {
            Pizza pizza;
            pizza = createPizza(type);
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();

            return pizza;
        }
    }
 //芝加哥风味Pizza店
    public class ChicagoStylePizzaStore : PizzaStore
    {
       public override Pizza createPizza(string type)
        {
            Pizza pizza = null;
            if (type == "cheese")//让子类决定该创建什么对象
            {
                pizza = new ChicagoStyleCheesePizza();
            }
            else if (type == "clam")
            {
                pizza = new ChicagoStyleClamPizza();
            }
            else if (type == "pepperoni")
            {
                pizza = new ChicagoPepperoniPizza();
            }
            else if (type == "veggie")
            {
                pizza = new ChicagoVeggiePizza();
            }
            return pizza;
        }
    }
//纽约风味Pizza店
    public class NYStylePizzaStore : PizzaStore
    {
        public override Pizza createPizza(string type)
        {
            Pizza pizza = null;
            if (type == "cheese")
            {
                pizza = new NYStyleCheesePizza();
            }
            else if (type == "clam")
            {
                pizza = new NYStyleClamPizza();
            }
            else if (type == "pepperoni")
            {
                pizza = new NYStylePepperoniPizza();
            }
            else if (type == "veggie")
            {
                pizza = new NYStyleVeggiePizza();
            }
            return pizza;
        }
    }
//pizza类
    public abstract class Pizza
    {
        public string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public string dough;//面团
        public string sauce;//调料
        public ArrayList toppings = new ArrayList();

        public void prepare()
        {
            Console.WriteLine("preparing: " + name);
            Console.WriteLine("Tossing dough……");
            Console.WriteLine("Adding sauce……");
            Console.WriteLine("Adding Toppings……");
            for (int i = 0; i < toppings.Count;i++ )
            {
                Console.WriteLine("   " + toppings[i]);
            }
        }
        public void bake()
        {
            Console.WriteLine("Bake for 25 minutes at 350");
        }
        public void cut()
        {
            Console.WriteLine("cutting the pizza into diagonal slices");
        }
        public void box()
        {
            Console.WriteLine("place pizza into box");
        }
    }
//芝加哥风味的奶酪Pizza,这个类实现了自己的切Pizza方法。
    public class ChicagoStyleCheesePizza : Pizza
    {
        public ChicagoStyleCheesePizza()
        {
            Name = "Chicago style deep dish Cheese pizza";
            dough = "extra thick crust dough";
            sauce = "plum potato sauce";

            toppings.Add("shredded mozzarella Cheese");

        }

        public void cut()
        {
            Console.WriteLine("Cutting the pizza into square slices");
        }
    }
static void Main(string[] args)
        {
            PizzaStore nyStore = new NYStylePizzaStore();
            PizzaStore chicagoStore = new ChicagoStylePizzaStore();

            Pizza pizza = nyStore.orderPizza("cheese");
            Console.WriteLine("Ethan ordered a " + pizza.Name+"\n");

            pizza = chicagoStore.orderPizza("cheese");
            Console.WriteLine("Jole oedered a " + pizza.Name + "\n");

            Console.ReadKey();
        }

 

其他的几类Pizza的子类就不一一列出来了。
4、设计原则

     4.1、解耦  工厂方法用来处理对象的创建,并将这样的行为封装在子类中,这样,客户程序中关于超类的代码就和子类对象创建代码解耦了。

     4.2、依赖倒置原则:要依赖抽象,而不依赖具体。这个原则是说不能让高层组件依赖底层组件,并且不管是高层组件还是底层组件,两者都应该依赖于抽象。这是什么意思呢?在我们这个例子中,pizzaStore就是个高层组件,而那些具体的pizza就是h底层组件。如果按照我们最初的按照简单工厂的方法实现的话,就或出现高层组件依赖于底层组件的现象。现在,我们用工厂方法实现之后,这两个组件都开始依赖Pizza这个抽象。那么“倒置”到底发生在什么地方?看看,我们的类图,就能发现,底层组件现在依赖于高层抽象,同样的,高层组件也依赖于相同的抽象。

   

posted on 2013-04-05 17:20  雨过晴空  阅读(198)  评论(0编辑  收藏  举报

导航