工厂模式解析

来源:互联网 发布:用什么软件优化游戏好 编辑:程序博客网 时间:2024/05/16 16:00

 

Factory Method

 

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

 

 Factory method

 

public interface Creator {

       public void factoryMethod();

       public void anOperation();

}

 

public class ConcreteCreator implements Creator {

       public void factoryMethod() {

              return new ConcreteProduct();

       }

}

 

Client端的使用:

List 1

Creator factory = new ConcreteCreator();

Product product = factory.factoryMethod();

 

 

解析:

Ø         不使用设计模式时,代码如下:

Product product = new ConcreteProduct();                       // A        

ConcreateProduct product = new ConcreteProduct();       // B

Ø         A直接违反了依赖倒转原则product将依赖于具体的ConcreteProduct类。更有甚者,B直接产生了一个具体产品,造成以后使用此product的对象也不得不依赖于具体的ConcreteProduct类。这是非常容易被疏忽的地方。

Ø         此模式体现了一个模式思想:将可变因素封装起来,并向外界提供一个不变的接口。上例中,所有的可变因素都抽象、封装到一个Creator的接口中,而Product的产生只依赖于此接口的factoryMethod()方法。

Ø         List 1中,我们的目标是对于任何一个实现了Product接口的 product,应当都由实现了Creator接口的factory来自动产生,其代码应恒为:

Product product = factory.factoryMethod()

这样,即使以后出了新的产品,这条语句都不会改变。这正是-闭原则的具体实现。而要做到这一点,我们必须使用

Creator factory = new ConcreteCreator();

的语句。这就出现了一个硬编码的new语句,而且new的后面直接绑定了一个具体的ConcreteCreator类,在以后出现新的product后,还得必须在此处修改这个相应的ConcreteCreator类,是否违反了-闭原则

Ø         是的,部分违反了-闭原则。对“软件应当对扩展开放”来讲,它做到了,但违反了“对修改关闭”。这是因为,在Java中,任何对象都必须通过new来创建,而且不能通过new来创建接口或抽象类,即使运用了各种设计模式之后依旧不可避免。因此,对new ConcreteCreator(),我们做不了其他文章。但别忘了,我们的目标是要得到一个Product,而不是一个ConcreteCreator,这个ConcreteCreator对象是为了帮助我们灵活地获得Product而额外增加的对象。

Ø         这种方式让我们获得几个好处:一是Product product = factory.factoryMethod()的目标代码不会改变;二是在生成具体的ConcreteCreator时,我们并未立即生成Product,只有在调用factory.factoryMethod()的方法后才产生Product。这种解耦是我们借以实现Product product = factory.factoryMethod()的重要保障;三是Creator factory = new ConcreteCreator();体现了里氏替换原则:任何基类可以出现的地方,子类一定可以出现。通过这种替换,我们做到了灵活与不变相统一:我们可以指定不同的工厂,却可以使用相同的代码生成不同的产品。四是对于Creator factory来讲,由于它不负责生成具体的产品,因此它没必要“知道”Client需要得到什么要的产品,以及应该如何生成这种产品。它把这项工作交给实现了其接口的ConcreteCreator来完成,从而保证了该类的纯洁性与粗颗粒度。五是我们可以把具体工厂的类或实例,甚至是相应的字符串以参数的形式传入实现了Creaotr接口的某个类,让其自己指派具体的工厂类,从而将ConcreteCreator这个可变的因素再次封装起来。

Ø         这是一种典型的delegation:委派他人完成细节工作,自己大可不必事事躬亲。自己不瞎忙,还可让他人人尽其才,物尽其用。