HeadFirst 设计模式笔记(四)—— 工厂模式

来源:互联网 发布:mac装win10连wifi没网 编辑:程序博客网 时间:2024/04/30 00:28
http://blog.csdn.net/tangwing/article/details/8454114
当我们使用“new”时我们就是在针对实现编程,这会使代码缺乏弹性。当然我们不可能避免在Java中使用new,真正需要考虑的是系统可能面对的“改变”。我们需要尽量隔离掉可能发生改变的部分。针对实现编程时,我们的代码中涉及到太多具体类,以后只要我们的系统需要改变,我们就不得不修改大量代码;而针对接口编程可以使得我们的代码更灵活,因为它涉及到的不是具体对象,而是一类对象。

一个设计应该“对扩展开放,对修改关闭”。有时我们需要把创建对象的动作封装起来,这就是工厂(factory)模式。工厂处理创建对象的细节。在本章的例子里,我们需要根据情况创建不同类型的Pizza,如果直接写成:
[java] view plaincopy
  1. PizzaStore类中  
  2. public Pizza orderPizza(String type) {  
  3. Pizza pizza;  
  4. if (type.equals("cheese")) {  
  5. pizza = new CheesePizza();  
  6. else if (type.equals("pepperoni")) {  
  7. pizza = new PepperoniPizza();  
  8. else if (type.equals("clam")) {  
  9. pizza = new ClamPizza();  
  10. else if (type.equals("veggie")) {  
  11. pizza = new VeggiePizza();  
  12. }  
  13. pizza.prepare();  
  14. pizza.bake();  
  15. pizza.cut();  
  16. pizza.box();  
  17. return pizza;  
  18. }  


以后每当有新的pizza出现我们都不得不修改此处代码。使用“简单工厂”模式,我们创建PizzaFactory类并实现createPizza(String Type)方法创建并返回相应的pizza。现在,我们将上面代码中的if-else块换为pizza = factory.createPizza(type);即可。

乍一看上去好像我们只是把代码换了个位置,并无实际意义,但是要知道PizzaFactory不只是用在orderPizza这一方法中,所有其他涉及到pizza对象使用的地方都可以使用PizzaFactory,以后如果有新的pizza种类加入只需修改createPizza方法即可。

注意:有时人们使用静态方法的方式实现简单的工厂,这样做的缺点在于不能使用继承改变创建方法的行为。
上面只是一个小例子,我们称之为“简单工厂”模式。书中提到的另外两种工厂模式为:

工厂方法模式(Factory Method Pattern)
现在考虑有PizzaStore有一些子类(加盟店),他们有可能对pizza的做法进行一些改良,即createPizza方法需要升级。工厂方法的做法是,在基类中建立一个形为abstract Product factoryMethod(String type); 的方法,作为工厂方法,负责创建对象,子类可以通过改写这一方法来改变创建对象的具体过程。

所有工厂模式都是为了封装对象的创建,工厂方法模式让子类来决定如何创建对象,来达到封装的目的。

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。基类中的其他类可以自由使用这一方法而不用考虑它到底返回的是怎样的对象。如何返回要根据子类的实现。(多态)

“简单工厂”把全部的事情在一个地方处理完,而“工厂方法”创建了一个框架,让子类决定如何实现。

抽象工厂模式:提供一个接口,用于创建一个对象家族,而无需指定具体类。
工厂方法只涉及到创建一个对象的情况,有时我们需要一族对象,比如书中的例子:原料家族。制作pizza需要很多原料,每个都需要一个工厂方法。这时我们把所有涉及到创建对象的方法集合到一起成为一个接口。使用者针对这个接口编程,而接口由具体的类来实现。这样一来我们可以根据情况把相应的实现此接口的类传递给使用者。

另外书中还提到一些设计原则。
依赖倒置原则(Dependency Inversion Principle):要尽量依赖抽象,不要依赖具体类。
几点原则(根据情况):
变量不要持有具体类的引用,使用工厂。
不要让类派生自具体类,这样就会依赖具体类。
不要覆盖基类中的方法,否则说明这个基类并不是一个适合被继承的对象。
0 0
原创粉丝点击