对如何轻松解决类实例化进程有任何想法。
当您看到一个新的运算符时,您正在实例化一个具体的类。当你有一整套相关的具体类时,你经常被迫编写这样的代码:
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;
}
}
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;
}
}
// 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 类
产品分类
工厂方法模式定义了用于创建对象的接口,但允许子类决定要实例化哪个类。
在我们上面的代码示例**(类比)**中:
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。工厂方法不是遵循依赖反转原则的唯一技术,但它是更强大的技术之一。
“依赖反转原则”这个名称之所以存在,是因为它颠覆了你通常对户外设计的思考方式。
现在我们要建造一个工厂来生产我们的原料;工厂将负责创造成分家族中的每种成分。换句话说,工厂将需要制作面团、酱汁、奶酪等。
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();
}
}
抽象工厂模式提供了一个接口,用于创建相关或依赖对象的族,而无需指定其具体类。
我们当然已经看到,抽象工厂允许客户使用抽象接口来创建一组相关产品,而无需了解(或关心)实际生产的具体产品。通过这种方式,客户与具体产品的任何细节脱钩。
工厂设计模式和抽象工厂设计模式都是用于封装对象创建、促进松耦合和促进软件设计灵活性的创作设计模式。以下是每个的摘要:
工厂设计模式:
抽象工厂设计模式:
总之,这两种工厂设计模式都为创建对象提供了解决方案,同时促进了软件设计的松耦合和灵活性。工厂方法模式通过继承将对象创建委托给子类,而抽象工厂模式则依赖于对象组合来创建相关对象的族。