设计模式之工厂模式

前端之家收集整理的这篇文章主要介绍了设计模式之工厂模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

当我们只用new去创建一个类时,我们就在针对这个具体类编程。如果能够不使用具体类,而是针对接口编程,将会对以后扩展有很大方便。

情景:

你是一个披萨店的老板,披萨有很多种类。

我们可能需要这么做

</span><span style="color: #0000ff;"&gt;if</span> (type == <span style="color: #800000;"&gt;A</span><span style="color: #000000;"&gt;) { pizza </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; APizza(); } </span><span style="color: #0000ff;"&gt;else</span> <span style="color: #0000ff;"&gt;if</span> (type == <span style="color: #800000;"&gt;B</span><span style="color: #000000;"&gt;) { pizza </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; BPizza(); } </span><span style="color: #0000ff;"&gt;else</span> <span style="color: #0000ff;"&gt;if</span> (type == <span style="color: #800000;"&gt;C</span><span style="color: #000000;"&gt;) { pizza </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; CPizza(); } ... </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; 制作披萨订单的其他操作</span>

}

但是以后我们可能会有D,E,F....之列的更多的披萨。我们必须重新修改这份代码

根据“封装变化”的设计原则,我们需要把创建对象的部分封装起来。

= </span><span style="color: #0000ff;"&gt;if</span> (type.equals("A"<span style="color: #000000;"&gt;)) { pizza </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; APizza(); } </span><span style="color: #0000ff;"&gt;else</span> <span style="color: #0000ff;"&gt;if</span> (type.equals("B"<span style="color: #000000;"&gt;)) { pizza </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; BPizza(); } </span><span style="color: #0000ff;"&gt;else</span> <span style="color: #0000ff;"&gt;if</span> (type.equals("C"<span style="color: #000000;"&gt;)) { pizza </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; CPizza(); } </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; pizza; }

}

这样在制作订单时只需在工厂取一个Pizza就可以了。

</span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; PizzaStore(SimplePizzaFactory factory) { </span><span style="color: #0000ff;"&gt;this</span>.factory =<span style="color: #000000;"&gt; factory; } </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; Pizza orderPizza(String type) { Pizza pizza; pizza </span>=<span style="color: #000000;"&gt; factory.createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.<a href="https://www.jb51.cc/tag/Box/" target="_blank" class="keywords">Box</a>(); </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; pizza; }

}

现在有很地区要建立披萨店的分店,你希望所有的店都有相同的流程,但是不同的地区会有不同的口味,比如有些地方只吃DEF口味的披萨,也就是说不同地区要有不同的工厂,没有方法把Pizza的制作活动全部局限于PizzaStore类呢?

方法是把createPizza放进PizzaStore类中,并设置成抽象方法,具体实现由每一个地区的子类完成。

</span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; Pizza orderPizza(String type) { Pizza pizza; pizza </span>=<span style="color: #000000;"&gt; createPizza(type); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.<a href="https://www.jb51.cc/tag/Box/" target="_blank" class="keywords">Box</a>(); </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; pizza; } </span><span style="color: #0000ff;"&gt;abstract</span><span style="color: #000000;"&gt; Pizza createPizza(String type);

}

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

Product factoryMethod(String type) 

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

我们最一开始的代码,PizzaStore的实现是依赖于具体Pizza类的,使用工厂模式后,它已经不再依赖于具体的披萨类,也就是减少了对具体类的依赖。

设计原则:依赖倒置原则(Dependency Inverseion Principle)

要依赖抽象,不要依赖具体类。

 这个原则说明了,不要让高层组件依赖底层组件,而且,不管高层组件还是底层组件,两者都应该依赖抽象。

使用了工厂方法模式之后,PizzaStore类依赖Pizza这个接口,而具体的APizza,BPizza等具体披萨类也依赖于Pizza这个接口,这就是一种依赖倒置。

………………

现在又有一个新的问题

就是具体Pizza的制作。上面没有写具体披萨的制作过程,默认都是一样的。但是!不同地区用到原料也可能有不同,例如A地产辣椒和B地是不一样的,于是,我们还应该给Pizza写一个原料工厂~~~

首先为工厂定义一个接口

为每一个地区创建一个原料工厂,比如纽约的原料工厂

NYPizzaIngredientFactory @Override </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; Dough createDough() { </span><span style="color: #0000ff;"&gt;return</span> <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; ThinCrustDough(); } @Override </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; Sauce createSauce() { </span><span style="color: #0000ff;"&gt;return</span> <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; MarinaraSauce(); } @Override </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; Cheese createCheese() { </span><span style="color: #0000ff;"&gt;return</span> <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; ReggianoCheese(); } @Override </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; Veggies[] createVeggies() { Veggies[] veggies </span>= { <span style="color: #0000ff;"&gt;new</span> Garlic(),<span style="color: #0000ff;"&gt;new</span> Onion(),<span style="color: #0000ff;"&gt;new</span> Mushroom(),<span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; RedPepper() }; </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; veggies; } @Override </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; Pepperoni createPepperoni() { </span><span style="color: #0000ff;"&gt;return</span> <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; SlicedPepperni(); } @Override </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; Clams createClam() { </span><span style="color: #0000ff;"&gt;return</span> <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; FreshClams(); }

}

抽象的Pizza类

String name; Dough dough; Sauce sauce; Veggies veggies[]; Cheese cheese; Pepperoni pepperoni; Clams clams; </span><span style="color: #0000ff;"&gt;abstract</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; prepare(); </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; bake() { System.out.println(</span>"Bake for 25 minutes at 350."<span style="color: #000000;"&gt;); } </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; cut() { System.out.println(</span>"Cutting the pizza into diagonal slices."<span style="color: #000000;"&gt;); } </span><span style="color: #0000ff;"&gt;public</span> <span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; <a href="https://www.jb51.cc/tag/Box/" target="_blank" class="keywords">Box</a>() { System.out.println(</span>"Place pizza in official PizzaStore <a href="https://www.jb51.cc/tag/Box/" target="_blank" class="keywords">Box</a>."<span style="color: #000000;"&gt;); } </span><span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; setName(String name) { </span><span style="color: #0000ff;"&gt;this</span>.name =<span style="color: #000000;"&gt; name; } String getName() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; name; } </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; String toString() { </span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; name; }

}

具体的Pizza类。每个Pizza的制作流程其实是一样的。只有原料不同,同时原料会和地点有关。为具体的类添加一个原料工厂。

CheesePizza PizzaIngredientFactory ingredientFactory; </span><span style="color: #0000ff;"&gt;public</span><span style="color: #000000;"&gt; CheesePizza(PizzaIngredientFactory ingredientFactory) { </span><span style="color: #0000ff;"&gt;this</span>.ingredientFactory =<span style="color: #000000;"&gt; ingredientFactory; } @Override </span><span style="color: #0000ff;"&gt;void</span><span style="color: #000000;"&gt; prepare() { System.out.println(</span>"Preparing " +<span style="color: #000000;"&gt; name); dough </span>=<span style="color: #000000;"&gt; ingredientFactory.createDough(); sauce </span>=<span style="color: #000000;"&gt; ingredientFactory.createSauce(); cheese </span>=<span style="color: #000000;"&gt; ingredientFactory.createCheese(); }

}

纽约的PizzaStore类

NYPizzaStore @Override Pizza createPizza(String item) { Pizza pizza </span>= <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;; PizzaIngredientFactory ingredientFactory </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; NYPizzaIngredientFactory(); </span><span style="color: #0000ff;"&gt;if</span> (item.equals("cheess"<span style="color: #000000;"&gt;)) { pizza </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; ChessPizza(ingredientFactory); } </span><span style="color: #0000ff;"&gt;else</span> <span style="color: #0000ff;"&gt;if</span> (item.equals("veggie"<span style="color: #000000;"&gt;)) { pizza </span>= <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; VeggiePizza(); pizza.setName(</span>"New York Style Veggie Pizza."<span style="color: #000000;"&gt;); } </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt; else if .... 还有其他种类的Pizza </span> <span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; pizza; }

}

完成~~

我们引入了新类型的工厂,也就是所谓的抽象工厂,来创建披萨家族。

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

抽象工厂允许客户使用抽象类的接口来创建一组相关的产品,而不需要知道(或关心)实际产出的具体产品是什么。这样一来,客户就从具体产品中被解耦。

类图

工厂方法模式通过继承,而抽象工厂模式是通过组合实现。

抽象工厂是用来创建一个产品家族的抽象类型,可以把一群相关产品集合起来。

原文链接:https://www.f2er.com/javaschema/69831.html

猜你在找的设计模式相关文章