java设计模式之工厂方法

来源:互联网 发布:电魂网络千股千评 编辑:程序博客网 时间:2024/04/27 23:49

工厂方法模式使用的频率非常高,在我们日常的开发中总能见到它的身影。其定义为:Define an interface for creating an object,but let subclasses deide which class to instantiate.Factory Method lets a class defer instantitaion to subclasses.(定义一二个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使用一个类的实例化延迟到其子类。)

下面笔者提供一个比较实用的通用源码。

Product.java 抽象产品类,具体的产品类可以有多个,都集成于抽象产品类

package com.jaynol.designpatterns.factorymethod;public abstract class Product {/** * 产品类公共方法  * 可以考虑增加final关键字,防止子类重写,因为重写后会破坏封装性 */public void method1(){//业务逻辑实现}//抽象方法,供子类做个性化扩展public abstract void method2();}


ConcreteProduct1.java 具体产品类

package com.jaynol.designpatterns.factorymethod;public class ConcreteProduct1 extends Product{@Overridepublic void method2() {//业务逻辑实现System.out.println("ConcreteProduct1 业务逻辑");}}


ConcreteProduct2.java 具体产品类

package com.jaynol.designpatterns.factorymethod;public class ConcreteProduct2 extends Product{@Overridepublic void method2() {//业务逻辑实现System.out.println("ConcreteProduct2 业务逻辑");}}

Creator.java 抽象工厂

package com.jaynol.designpatterns.factorymethod;public abstract class Creator {/** * 创建一个产品对象,其输入参数类型可以自行设置 * 通常为String,Enum,Class等,当然也可以为空 */public abstract <T extends Product> T createProduct(Class<T> c);}


ConcreteCreator.java 具体工厂
package com.jaynol.designpatterns.factorymethod;public class ConcreteCreator extends Creator{@Overridepublic <T extends Product> T createProduct(Class<T> c) {Product product = null;try{product = (Product) Class.forName(c.getName()).newInstance();}catch(Exception e){//异常处理}return (T)product;}}

Client.java 场景类

package com.jaynol.designpatterns.factorymethod;public class Client {/** * @param args */public static void main(String[] args) {//创建一个产Product的工厂Creator creator = new ConcreteCreator();//生产concreteProduct1这个类产品ConcreteProduct1 concreteProduct1 = creator.createProduct(ConcreteProduct1.class);concreteProduct1.method2();//生产concreteProduct2这个类产品ConcreteProduct2 concreteProduct2 = creator.createProduct(ConcreteProduct2.class);concreteProduct2.method2();}}

工厂方法模式的优点:

1.良好的封装性,代码结构清晰。一个对象的创建是有条件约束的,如一个调用者需要一个具体的产品对象,只要知道这个产品的类名(或约束字符串)就可以了,不用知道创建对象的艰辛过程,降低模块间的耦合。

2.工厂方法模式的扩展性非常优秀。在增加产品类的情况下,只要适当地修改具体的工厂类或扩展一个工厂类,就可以完成“拥抱变化”。例如在我们的例子中,需要增加一个ConcreteProduct3产品,只需要增加一个ConcreteProduct3类,工厂类都不用任何修改就能完成系统的扩展。

3.屏蔽产品类。这一特点非常重要,产品类的实现如何变化,调用者都不需要关心,它只需要关心产品的接口,只要接口保持不变,系统中的上层模块就不会发生变化。因为产品类的实例化工作是由工厂类负责的。一个产品的对象具体由那个一个产品生成是由工厂类决定的。在数据库开发中,大家因应该能够深刻体会到工厂方法模式的好处:如果使用JDBC连接数据库,数据库从MySQL切换到Oracle,需要改动的地方就是切换一下驱动名称(前提条件是SQL语句是标准语句),其他的都不需要修改,这是工厂方法模式灵活性的一个直接案例。

4.工厂方法模式是典型的解耦框架。高层模块只需要知道产品的抽象类,其他的实现类都不用关心,符合迪米特法则,则我不需要的就不要去交流;也复核依赖倒置原则,只依赖产品的抽象;当然也复核里氏替换原则,使用产品子类替换产品父类,没问题!

工厂方法模式扩展:

1.缩小为简单工厂模式

我们这样考虑一个问题:一个模块仅需要一个工厂类,没有必要把它生产出来,使用静态的方法就可以了,根据这一要求,笔者把上面例子中的Creator修改一下,代码如下:

package com.jaynol.designpatterns.factorymethod;public class SimpleFactoryMethod {public static <T extends Product> T createProduct(Class<T> c) {Product product = null;try{product = (Product) Class.forName(c.getName()).newInstance();}catch(Exception e){//异常处理}return (T)product;}}
通过这样的修改,场景类修改如下:

package com.jaynol.designpatterns.factorymethod;public class Client {/** * @param args */public static void main(String[] args) {//生产concreteProduct1这个类产品ConcreteProduct1 concreteProduct1 = SimpleFactoryMethod.createProduct(ConcreteProduct1.class);concreteProduct1.method2();//生产concreteProduct2这个类产品ConcreteProduct2 concreteProduct2 = SimpleFactoryMethod.createProduct(ConcreteProduct2.class);concreteProduct2.method2();}}

2.升级为多个工厂

当我们做一个比较复杂的项目时,经常会遇到初始化一个对象是一件很复杂的事情,并且需要针对不同的产品的生产过程做定制,如果把这些逻辑都放在一个工厂里代码结构就不清晰了。例如,上面例子中的两个产品ConcreteProduct1和ConcreteProduct2,需要在生产ConcreteProduct1时给它初始化名字为ConcreteProduct1而ConcreteProduct2则需要初始化名字为ConcreteProduct2,把这段逻辑通过if eslse写在一个Creator里就不易于扩展和维护了。为了满足这种需求,需要把上面的工厂方法模式升级为多个工厂的方式,代码如下:

抽象工厂:

package com.jaynol.designpatterns.factorymethod;public abstract class AbstractCreator {protected abstract Product createProduct();}

生产ConcreteProduct1的工厂:

package com.jaynol.designpatterns.factorymethod;public class ConcreteProduct1Creator extends AbstractCreator{@Overrideprotected Product createProduct() {/** * 可在此处实现初始化的逻辑 */return new ConcreteProduct1();}}

生产ConcreteProduct2的工厂:

package com.jaynol.designpatterns.factorymethod;public class ConcreteProduct2Creator extends AbstractCreator{@Overrideprotected Product createProduct() {/** * 可在此处实现初始化的逻辑 */return new ConcreteProduct2();}}

场景类如下:

package com.jaynol.designpatterns.factorymethod;public class Client {/** * @param args */public static void main(String[] args) {//生产concreteProduct1这个类产品Product concreteProduct1 = (new ConcreteProduct1Creator()).createProduct();concreteProduct1.method2();//生产concreteProduct2这个类产品Product concreteProduct2 = (new ConcreteProduct2Creator()).createProduct();concreteProduct2.method2();}}




原创粉丝点击