工厂设计模式和抽象工厂设计模式

作者:微信公众号:【架构师老卢】
2-19 18:22
26

概述:对如何轻松解决类实例化进程有任何想法。当您看到一个新的运算符时,您正在实例化一个具体的类。当你有一整套相关的具体类时,你经常被迫编写这样的代码:Duck duck; if (picnic) {      duck = new MallardDuck();  } else if (hunting) {      duck = new DecoyDuck();  } else if (inBathTub) {      duck = new RubberDuck();  }新关键字没有问题,但问题是如何应对未来的变化。编程到一个接口,你可以将自己与许多变化隔离开来。如果代码被写入接口

对如何轻松解决类实例化进程有任何想法。

当您看到一个新的运算符时,您正在实例化一个具体的类。当你有一整套相关的具体类时,你经常被迫编写这样的代码:

Duck duck;  
if (picnic) {   
    duck = new MallardDuck();   
} else if (hunting) {   
    duck = new DecoyDuck();   
} else if (inBathTub) {   
    duck = new RubberDuck();   
}

新关键字没有问题,但问题是如何应对未来的变化。
编程到一个接口,你可以将自己与许多变化隔离开来。如果代码被写入接口,则它将与通过子类型多态性实现该接口的任何类一起使用。

现在让我们以披萨制作和烘焙过程为例。

public class PizzaStore  
    {  
        public pizza orderPizza()  
        {  
            pizza pizza;  
            //This is what varies. As the pizza selection changes   
            //over time, you'll have to modify this code over and over  
            if (Type.Equals("cheese"))  
            {  
                pizza = new CheesePizza();  
            }  
            else if (Type.Equals("pepperoni"))  
            {  
                pizza = new PepperoniPizza();  
            }  
            else if (Type.Equals("clam"))  
            {  
                pizza = new ClamPizza();  
            }  
            else if (Type.Equals("veggie"))  
            {  
                pizza = new VeggiePizza();  
            }  
            //This is what we expect to stay the same.   
            // For the most part, preparing, cooking, and packaging  
            //a pizza has remained the same for years and years  
            pizza.prepare();  
            pizza.bake();  
            pizza.cut();  
            pizza.box();  
            return pizza;  
        }  
    }

策略设计模式

在微妙的策略设计模式中,意味着将控制权交给客户,客户实际上决定实施...

一种设计原则,用于识别应用程序中不同的方面,并将它们与保持不变的方面区分开来。

封装对象创建

因此,我们将对象创建部分分开,以及我们将如何做到这一点,您将在本博客的后面看到。但现在我将这个新对象命名为:我们称它为工厂。工厂处理对象创建的细节。一旦我们有了 SimplePizzaFactory,我们的 orderPizza() 方法就会成为该对象的客户端。

public class SimplePizzaFactory {  
     public Pizza createPizza(String type) {  
     Pizza pizza = null;  
     if (Type.Equals("cheese"))  
      {  
          pizza = new CheesePizza();  
      }  
      else if (Type.Equals("pepperoni"))  
      {  
          pizza = new PepperoniPizza();  
      }  
      else if (Type.Equals("clam"))  
      {  
          pizza = new ClamPizza();  
      }  
      else if (Type.Equals("veggie"))  
      {  
          pizza = new VeggiePizza();  
      }  
     return pizza;  
     }  
}

重新设计 PizzaStore 类

public class PizzaStore {  
   SimplePizzaFactory factory;  
   public PizzaStore(SimplePizzaFactory factory) {  
     this.factory = factory;  
   }  
   public Pizza orderPizza(String type) {  
     Pizza pizza;  
     pizza = factory.createPizza(type);  
     pizza.prepare();  
     pizza.bake();  
     pizza.cut();  
     pizza.box();  
     return pizza;  
   }  
}

orderPizza() 方法使用工厂通过简单地传递订单类型来创建其比萨饼。

披萨 = factory.createPizza(type);

orderPizza() 方法使用工厂通过简单地传递订单类型来创建其比萨饼。请注意,我们已将 new 运算符替换为 factory 对象上的 create 方法。这里没有更多具体的实例!我们知道,对象组合允许我们在运行时动态地改变行为(以及其他东西),因为我们可以换入和换出实现。

简单工厂的定义

把Simple Factory看作是一次热身。接下来,我们将探讨两种重型模式,它们都是工厂。但别担心,还有更多披萨要来!

***再次提醒:在设计模式中,“实现接口”一词并不总是意味着“通过在类声明中使用”implements“关键字来编写实现 Java 接口的类”。在短语的一般用法中,从超类型(可以是类 OR 接口)实现方法的具体类仍被视为该超类型的“实现接口”。

每个特许经营店可能都希望提供不同风格的比萨饼(纽约、芝加哥和加利福尼亚,仅举几例),具体取决于特许经营店所在的位置和当地比萨鉴赏家的口味。

如果我们去掉 SimplePizzaFactory 并创建三个不同的工厂,NYPizzaFactory、ChicagoPizzaFactory 和 CaliforniaPizzaFactory。

NYPizzaFactory nyFactory = new NYPizzaFactory();  
PizzaStore nyStore = new PizzaStore(nyFactory);  
nyStore.order(“Veggie”);  
ChicagoPizzaFactory chicagoFactory = new ChicagoPizzaFactory();  
PizzaStore chicagoStore = new PizzaStore(chicagoFactory);  
chicagoStore.order(“Veggie”);

披萨店的框架

public abstract class PizzaStore {  
   public Pizza orderPizza(String type) {  
     Pizza pizza;  
     pizza = createPizza(type);  
     pizza.prepare();  
     pizza.bake();  
     pizza.cut();  
     pizza.box();  
     return pizza;  
   }  
   abstract Pizza createPizza(String type);  
}

允许子类决定

public class NYPizzaStore extends PizzaStore {  
   Pizza createPizza(String item) {  
     if (item.equals(“cheese”)) {  
     return new NYStyleCheesePizza();  
     } else if (item.equals(“veggie”)) {  
     return new NYStyleVeggiePizza();  
     } else if (item.equals(“clam”)) {  
     return new NYStyleClamPizza();  
     } else if (item.equals(“pepperoni”)) {  
     return new NYStylePepperoniPizza();  
     } else return null;  
   }  
}
  1. createPizza() 返回一个 Pizza,该子类完全负责它实例化的具体 Pizza
  2. NYPizzaStore 扩展了 PizzaStore,因此它继承了 orderPizza() 方法
  3. 我们必须实现 createPizza(),因为它在 PizzaStore 中是抽象的。
  4. 请注意,超类中的 orderPizza() 方法不知道我们正在创建哪个 Pizza;它只知道它可以准备、烘烤、切割和装箱!

组合代码

// Base class of all pizza   
public abstract class Pizza  
    {  
        public String name;  
        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 virtual void bake()  
        {  
            Console.WriteLine("Bake for 25 minutes at 350") ;  
        }  
        public virtual void cut()  
        {  
            Console.WriteLine("Cutting the pizza into diagonal slices");  
        }  
  
        public virtual void box()  
        {  
            Console.WriteLine("Place pizza in official PizzaStore box");  
        }  
        public virtual String getName()  
        {  
            return name;  
        }  
    }  
// Abstract base class of Factory SubClass  
public abstract class PizzaStore  
    {  
        public Pizza orderPizza(String type)  
        {  
            Pizza pizza;  
            pizza = CreatePizza(type);  
            Console.WriteLine("Current Object Type "+ pizza.GetType());  
            pizza.prepare();  
            pizza.bake();  
            pizza.cut();  
            pizza.box();  
            return pizza;  
        }  
        public abstract Pizza CreatePizza(String type);  
    }  
// Factory Class of Chicago Pizza Franchise  
public class ChicagoPizzaStore : PizzaStore  
    {  
        public override Pizza CreatePizza(String item) {  
            if (item.Equals("cheese")) {  
                return new NYStyleCheesePizza();  
            }  
            else return null;  
        }  
    }  
// Factory Class of NY Pizza Franchise  
public class NYPizzaStore: PizzaStore  
    {  
        public override Pizza CreatePizza(String item) {  
            if (item.Equals("cheese")) {  
                return new NYStyleCheesePizza();  
            }  
            else return null;  
        }  
    }  
  
public class ChicagoStyleCheesePizza: Pizza  
    {  
        public ChicagoStyleCheesePizza()  
        {  
            name = "Chicago Style Deep Dish Cheese Pizza";  
            dough = "Extra Thick Crust Dough";  
            sauce = "Plum Tomato Sauce";  
            toppings.Add("Shredded Mozzarella Cheese");  
        }  
        public override void cut()  
        {  
            Console.WriteLine("Cutting the pizza into square slices");  
        }  
    }  
public class NYStyleCheesePizza: Pizza  
    {  
        public NYStyleCheesePizza()  
        {  
            name = "NY Style Sauce and Cheese Pizza";  
            dough = "Thin Crust Dough";  
            sauce = "Marinara Sauce";  
            toppings.Add("Grated Reggiano Cheese");  
        }  
    }

运行代码

PizzaStore nyStore = new NYPizzaStore();  
PizzaStore chicagoStore = new ChicagoPizzaStore();  
Pizza pizza = nyStore.orderPizza("cheese");  
Console.WriteLine("shrinidhi ordered a " +pizza.getName() + "\n");  
pizza = chicagoStore.orderPizza("cheese");  
Console.WriteLine("Adarsh ordered a " +pizza.getName() + "\n"); 

OutPut-:

Current Object Type WebApplication1.Factory_Design.Concrete.NYStyleCheesePizza  
Preparing NY Style Sauce and Cheese Pizza  
Tossing dough...  
Adding sauce...  
Adding toppings:  
 Grated Reggiano Cheese  
Bake for 25 minutes at 350  
Cutting the pizza into diagonal slices  
Place pizza in official PizzaStore box  
shrinidhi ordered a NY Style Sauce and Cheese Pizza  
  
Current Object Type WebApplication1.Factory_Design.Concrete.NYStyleCheesePizza  
Preparing NY Style Sauce and Cheese Pizza  
Tossing dough...  
Adding sauce...  
Adding toppings:  
 Grated Reggiano Cheese  
Bake for 25 minutes at 350  
Cutting the pizza into diagonal slices  
Place pizza in official PizzaStore box  
Adarsh ordered a NY Style Sauce and Cheese Pizza

这种设计我之所以能够实现,是因为我实现了一个接口。

Creator 类

产品分类

另一个视角:平行类层次结构

工厂方法模式定义

工厂方法模式定义了用于创建对象的接口,但允许子类决定要实例化哪个类。

在我们上面的代码示例**(类比)**中:

  1. Creator 是 PizzaStore 抽象类
  2. Concrete Creator 是 ChicagoPizzaStore 或 NYPizzaStore 类
  3. Product 是 Pizza 抽象类
  4. 混凝土产品是 ChicagoStyleCheesePizza 或 NYStyleCheesePizza 类

从工厂模式到抽象工厂模式

public class DependentPizzaStore {  
 public Pizza createPizza(String style, String type) {  
   Pizza pizza = null;  
   if (style.equals(“NY”)) {  
   if (type.equals(“cheese”)) {  
   pizza = new NYStyleCheesePizza();  
   } else if (type.equals(“veggie”)) {  
   pizza = new NYStyleVeggiePizza();  
   } else if (type.equals(“clam”)) {  
   pizza = new NYStyleClamPizza();  
   } else if (type.equals(“pepperoni”)) {  
   pizza = new NYStylePepperoniPizza();  
   }  
   } else if (style.equals(“Chicago”)) {  
   if (type.equals(“cheese”)) {  
   pizza = new ChicagoStyleCheesePizza();  
   } else if (type.equals(“veggie”)) {  
   pizza = new ChicagoStyleVeggiePizza();  
   } else if (type.equals(“clam”)) {  
   pizza = new ChicagoStyleClamPizza();  
   } else if (type.equals(“pepperoni”)) {  
   pizza = new ChicagoStylePepperoniPizza();  
   }  
   } else {  
   System.out.println(“Error: invalid type of pizza”);  
   return null;  
   }  
   pizza.prepare();  
   pizza.bake();  
   pizza.cut();  
   pizza.box();  
   return pizza;  
 }  
}

查看对象依赖关系

依赖关系反转原理

然而,这是另一个流行的设计原则,用于许多设计模式。
依赖于抽象。不要依赖于具体的类。

它表明我们的高级组件不应依赖于我们的低级组件;相反,它们都应该依赖于抽象。

“高级”组件**是具有根据其他“低级”组件定义的行为的类。**例如,DependentPizzaStore 是一个高级组件,因为它的行为是根据比萨饼定义的——它创建所有不同的比萨饼对象,准备、烘烤、切割和装箱,而它使用的比萨饼是低级组件。

应用原则

虽然我们创建了一个抽象的 Pizza,但我们仍然在此代码中创建了具体的 Pizza。

应用 Factory 方法后,您会注意到我们的高级组件 PizzaStore 和我们的低级组件 pizzas 都依赖于抽象的 Pizza。工厂方法不是遵循依赖反转原则的唯一技术,但它是更强大的技术之一。

依赖倒置原理中的“倒置”在哪里?

“依赖反转原则”这个名称之所以存在,是因为它颠覆了你通常对户外设计的思考方式。

一些帮助您遵循原则的准则......

  1. 任何变量都不应包含对具体类的引用。
  2. 任何类都不应派生自具体类。
  3. 任何方法都不应重写其任何基类的已实现方法。

建立原料工厂

现在我们要建造一个工厂来生产我们的原料;工厂将负责创造成分家族中的每种成分。换句话说,工厂将需要制作面团、酱汁、奶酪等。

public interface PizzaIngredientFactory  
    {  
        public Dough createDough();  
        public Sauce createSauce();  
        public Cheese createCheese();  
        public Veggies[] createVeggies();  
        public Pepperoni createPepperoni();  
        public Clams createClam();  
    }  
public abstract class Pizza  
    {  
        public String name;  
        public String dough;  
        public String sauce;  
        public ArrayList toppings = new ArrayList();  
        public Veggies veggies[];  
        public Cheese cheese;  
        public Pepperoni pepperoni;  
        public Clams clam;  
        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 virtual void bake()  
        {  
            Console.WriteLine("Bake for 25 minutes at 350") ;  
        }  
        public virtual void cut()  
        {  
            Console.WriteLine("Cutting the pizza into diagonal slices");  
        }  
  
        public virtual void box()  
        {  
            Console.WriteLine("Place pizza in official PizzaStore box");  
        }  
        public virtual String getName()  
        {  
            return name;  
        }  
    }  
public class CheesePizza: Pizza  
    {  
        PizzaIngredientFactory ingredientFactory;  
        public CheesePizza(PizzaIngredientFactory ingredientFactory)  
        {  
            this.ingredientFactory = ingredientFactory;  
        }  
        public void prepare()  
        {  
            Console.WriteLine("Preparing " +name);  
            dough = ingredientFactory.createDough();  
            sauce = ingredientFactory.createSauce();  
            cheese = ingredientFactory.createCheese();  
        }  
    }  
  
public class ClamPizza : Pizza  
    {  
        PizzaIngredientFactory ingredientFactory;  
        public ClamPizza(PizzaIngredientFactory ingredientFactory)  
        {  
            this.ingredientFactory = ingredientFactory;  
        }  
        void prepare()  
        {  
            Console.WriteLine("Preparing " +name);  
            dough = ingredientFactory.createDough();  
            sauce = ingredientFactory.createSauce();  
            cheese = ingredientFactory.createCheese();  
            clam = ingredientFactory.createClam();  
        }  
    }  
  
 public class NYPizzaIngredientFactory : PizzaIngredientFactory  
    {  
        public Dough createDough()  
        {  
            return new ThinCrustDough();  
        }  
        public Sauce createSauce()  
        {  
            return new MarinaraSauce();  
        }  
        public Cheese createCheese()  
        {  
            return new ReggianoCheese();  
        }  
        public Veggies[] createVeggies()  
        {  
            Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };  
            return veggies;  
        }  
        public Pepperoni createPepperoni()  
        {  
            return new SlicedPepperoni();  
        }  
        public Clams createClam()  
        {  
            return new FreshClams();  
        }  
    }

抽象工厂模式定义

抽象工厂模式提供了一个接口,用于创建相关或依赖对象的族,而无需指定其具体类。

我们当然已经看到,抽象工厂允许客户使用抽象接口来创建一组相关产品,而无需了解(或关心)实际生产的具体产品。通过这种方式,客户与具体产品的任何细节脱钩。

总结

工厂设计模式和抽象工厂设计模式都是用于封装对象创建、促进松耦合和促进软件设计灵活性的创作设计模式。以下是每个的摘要:

工厂设计模式:

  • 工厂设计模式通过提供负责创建对象的中央接口或类来封装对象创建。
  • 工厂方法依赖于继承:对象创建被委托给子类,这些子类实现工厂方法来创建对象。
  • 工厂方法的目的是允许类将实例化延迟到其子类,从而在遵守公共接口的同时实现对象创建的灵活性。
  • 工厂方法通过减少应用程序对具体类的依赖来促进松耦合。

抽象工厂设计模式:

  • 抽象工厂设计模式依赖于对象组合来创建相关对象的系列,而无需公开其具体类。
  • 它定义了一个抽象工厂接口,其中包含用于创建相关对象的方法。
  • 具体工厂类实现此接口,以提供对象创建的特定实现。
  • 与依赖于继承的工厂方法不同,抽象工厂模式强调对象组合。
  • 抽象工厂模式允许客户端使用通用接口创建对象,而不依赖于特定的实现,从而促进了松散耦合。

总之,这两种工厂设计模式都为创建对象提供了解决方案,同时促进了软件设计的松耦合和灵活性。工厂方法模式通过继承将对象创建委托给子类,而抽象工厂模式则依赖于对象组合来创建相关对象的族。

相关留言评论
昵称:
邮箱:
阅读排行