headfirst设计模式学习体会(4)

  程序不可能仅仅由抽象构成,抽象类和接口在程序中是通过各种继承和实现产生大量的具体类来完善和扩充程序的功能的描述。而要程序真正运行起来,这些大量的具体类还需要在程序中被实例化。与大量的具体类打交道,必须谨慎地设计才能避免产生难以维护的代码。类的数量和具体实现在未来一变再变,这种变动首先影响到的就是客户程序中创建这些类的实例的代码,因为创建类的实例,总是面向具体的实现编程的。如果把实例化的对象称作产品,我们就不能让客户程序自己去生产这些产品,因为散落在客户程序中的实例化具体类的代码面对频繁地改动必然会带来维护上的困难。只有将“产品”委托给一个“工厂”去生产,才能实现程序松耦合的设计。
  工厂首先可以是一个对象,我们只要在客户程序中保存对该对象的引用,在需要实例化具体类的地方调用该对象的“生产方法”即可,而该对象的生产方法,就是对原来散落在客户程序中的“生产”行为的封装。工厂甚至可以就是一个静态的方法,即用一个静态方法封装“生产”行为,这个方法因此又被称为静态工厂。静态工厂不需要像前者那样在客户程序中还要保存对工厂对象的引用,但是静态工厂也不能像前者那样,通过继承工厂类来改变生产行为。最后,这两种工厂统称为简单工厂。
   简单工厂在处理简单的“生产”过程时可以发挥很好的作用,但是如果产品的种类很多(具体类的数量很多)或者生产过程很复杂(涉及到动态创建对象的一系列复杂判断),简单工厂可能就会显得有点力不从心了。首先简单工厂只是一个对象,直接面对大量的具体类编程,会使得它的“生产方法”太过于依赖这些具体类的实现,当具体类的数量增减或者实现有所变化的时候,简单工厂可能就要进行相应的代码修改。另一方面,客户程序中需要实例化对象的地方有着不同的动态创建逻辑,往往需要根据具体地对象使用者的类型来创建不同的产品类型。这种动态创建的过程全部交由一个简单工厂处理显然是不合适的,会导致代码复用性低,可维护性差等问题。因此我们需要对生产产品的过程做更进一步地抽象.
  设计原则:要依赖抽象,不要依赖具体类。
  这个原则被称为“依赖倒置原则”,它告诉我们要依赖抽象类,不要依赖具体类。我们来看看怎么将它运用到我们的工厂中。不同的具体类现在代表不同的产品(对象)类型,客户程序在需要产品的地方委托工厂生产产品。既然我们不能把所有产品的生产委托给一个工厂,那么我们就要建立多个工厂应对多个产品这种复杂的状况。而建立的规则是什么呢?在一个程序功能单元中,我们面对的具体类(产品种类)继承一个共同的抽象类(产品)。客户程序中需要实例化具体类的地方对应的是这样一个逻辑:工厂生产产品。而具体的实现则由客户程序中调用该产品的对象类型决定,即工厂A生产产品A,工厂B生产产品B……于是我们可以给工厂建立一个共同的抽象,然后分别建立不同搞得工厂来具体实现这个抽象,以生产不同的产品。最后将每一个具体的工厂与具体的使用对象类型联系起来。而每一个具体工厂所做的事情就是之前简单工厂所做的事情,只不过现在它们继承自共同的抽象。这样一来,我们只要客户程序面对工厂生产产品这个抽象,把客户程序从具体的实现中解耦了。
  根据具体工厂与使用该工厂产品的对象的联系方式,可以分为工厂方法模式和抽象工厂模式。工厂方法模式是在使用者对象的父类中加入生产方法,使得父类成为抽象类,具体的生产方法实现由具体的子类实现。该模式用到的是继承。而抽象工厂模式是定义一个接口,该接口包含一组方法来生产产品。而实现了这个接口的具体工厂子类具体实现这些方法,客户程序只需要保存对该接口的引用,在使用时会根据该引用实例变量来动态地实现产品族的生产(接口包含一组生产方法)。总的来说,工厂方法用到的是继承,而抽象工厂用到的是组合。
  工厂方法模式 定义类一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
  抽象工厂模式 提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。