简单工厂模式/工厂方法模式--Head First设计模式【笔记】

在了解工厂方法模式前,我们先来了解一下简单工厂模式

一、简单工厂模式

我家开了一个Pizza店,代码如下:

 public  class PizzaStore
    {
       public Pizza orderPizza(string type) 
       {
           Pizza pizza;

           //根据Pizza类型,我们实例化正确的具体类。
           //这里的任何Pizza都必须实现Pizza接口
           if (type.Equals("cheese")) 
           {
               pizza = new CheesePizza();
           }else if (type .Equals ("greek"))
           {
               pizza = new GreekPizza();
           }else if (type .Equals ("pepperoni"))
           {
               pizza = new PepperoniPizza();
           }

           //pizza 的一些制作流程
           pizza.prepare();
           pizza.bake();
           pizza.cut();
           pizza.box();
           return pizza;

       }
    }

看上面红色部分的代码,它是产生不同风味的Pizza的代码。

这样就存在一个问题:如果市场需求变化(出现新的风味的Pizza需求),那我们就要对这段代码一改再改。

违反了我们的设计原则:类应该对扩展开发,对修改关闭。

那怎么办?

想想我们的设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
我们把红色部分的代码剪切出来放到另一个对象SimplePizzaFactory中,由SimplePizzaFactory专门负责生产不同风味的Pizza。

//重做PizzaStore
public
class PizzaStore { //为PizzaStore加上一个对SimplePizzaFactory的引用 SimplePizzaFactory factory; //PizzaStore的构造器需要一个工厂作为参数 public PizzaStore(SimplePizzaFactory factory) { this.factory = factory; } public Pizza orderPizza(string type) { Pizza pizza; //orderPizza()方法通过简单传入订单类型来使用工厂创建Pizza pizza = factory.createPizza(type ); //pizza 的一些制作流程 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); return pizza; } }
//简单工厂
public
class SimplePizzaFactory { public Pizza createPizza(String type) { Pizza pizza = null;
//红色代码剪切到这里
if (type.Equals("cheese")) { pizza = new CheesePizza(); } else if (type.Equals("greek")) { pizza = new GreekPizza(); } else if (type.Equals("pepperoni")) { pizza = new PepperoniPizza(); } return pizza; } }

到这里你可能要问了:这么做有什么好处啊?似乎只是把问题搬到另一个对象罢了,问题依然存在。

答:别忘了,SimplePizzaFactory可以有许多的客户,虽然目前只看到orderPizza()方法是它的客户,

      然而,可能还有PizzaShopMenu(比萨店菜单)类,会利用这个工厂来取得比萨的价钱和描述。

      所以,把创建比萨的代码包装进一个类,当以后实现改变时,只需要修改这个类即可。

-----------------------------------------------------------

经过团队不断的努力,我家的Pizza店的产品深受消费者的喜欢,其他人的Pizza店想加盟我家的Pizza店。

加盟可以,但是我家的Pizza店有要求:要使用我家的代码,保证Pizza的制作流程能一致。

加盟店主也提出了一点自己的想法:希望工厂能够制作出加盟店本地(加盟店地址和我家的Pizza店不在同一区域)风味的Pizza。

 需求解析

制作流程一致,那我们很容易想到继承。加盟店继承我家的Pizza店的代码,那就能复用制作流程,保证制作流程一致性。

加盟店想要本地风味的Pizza,即加盟店想自己决定Pizza的风味,那么我们把PizzaStore类中的Pizza的创建代码pizza = factory.createPizza(type );改为一个抽象方法,让继承加盟店自己来实现。

额!!这不就是工厂方法模式吗?

工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

让我们看下代码吧:

//重写PizzaStore
public abstract class PizzaStore
    {
       
       public Pizza orderPizza(string type) 
       {
           Pizza pizza;

           //创建对象pizza的接口 
           pizza = createPizza(type );
           //pizza 的一些制作流程
           pizza.prepare();
           pizza.bake();
           pizza.cut();
           pizza.box();
           return pizza;

       }
       // 让子类决定实例化哪个类(即哪个风味的Pizza)
       protected abstract Pizza createPizza(String type);
    }
//本地加盟店 
public  class BenDiPizzaStore:PizzaStore 
    {
        // 什么风味的Pizza是由加盟店自己决定的
        protected override Pizza createPizza(string type)
        {
            Pizza pizza = null;
            if (type.Equals("ChicagoPizza"))
            {
                pizza = new ChicagoPizza();
            }
            else if (type.Equals("NYSPizza"))
            {
                pizza = new NYSPizza();
            }
           
            return pizza;
        }
    }
//加盟店中NYSPizza风味的Pizza
 class NYSPizza:Pizza 
    {
        public NYSPizza() 
        {
            name = "BenDi Style Sauce and Cheese Pizza";
            dough = "Thin Crust Dough";
            sauce = "Marinara Sauce";

            toppings.Add("Grated Reggiano Cheese");
        }
    }
//加盟店中 ChicagoPizza风味的Pizza
class ChicagoPizza:Pizza 
    {
        public ChicagoPizza() 
        {
            name = "BenDi Style Deep Dish Cheese Pizza";
            dough = "Extra Thick Crust Dough";
            sauce = "Plum Tomato Sauce";

            toppings.Add("Shredded Mozzarella Cheese"); }
//加盟店中ChicagoPizza风味的Pizza特殊切法,在流程一致的基础上,有加盟店本地化的元素。 void cut() { Console.WriteLine("Cutting the pizza into square slices"); } }

篇幅所限,我就只写了一个加盟店和两种风味的Pizza,有兴趣的朋友可以自己多些几个加盟店和不同风味的Pizza。

//重要角色  Pizza 
 public abstract  class Pizza
    {
       protected  string name;
       protected  string dough;
       protected string sauce;
       protected 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 in official PizzaStore box");
        }
        public string getName() 
        {
            return name;
        }
    }

 

调试下:Pizza开卖了!!!

 static void Main(string[] args)
        {
            PizzaStore bdStore = new BenDiPizzaStore();
            bdStore.orderPizza("ChicagoPizza");
            Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
            bdStore.orderPizza("NYSPizza");
            Console.ReadKey();
        }

显示:

待续:

抽象工厂模式:定义一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

     目前我的理解:我要创建一个对象,而这个对象有些相关或者说依赖的部分是变化的,是时常改动的。这时候我通过为这一系列定义一个接口,让变化实现这个接口。而对象的构造函数以这个接口为传入的参数,那么我们就可以调用这个接口的一系列变化,达到完整创建这个对象的目的。而这个一系列变化就不需要明确指定具体类,而是由创建实例对象时以实现这个接口的类做参数传进来的。(抽象工厂模式,我目前还无法用自己的话完整的表达出来,希望不要误导大家。先记这边,等理解深刻了用通俗易懂的方式展现给大家)。

posted on 2012-08-28 17:22  妖叨叨  阅读(875)  评论(0)    收藏  举报

导航