java设计模式之工厂方法

工厂方法模式使用的频率非常高,在我们日常的开发中总能见到它的身影。其定义为: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{

	@Override
	public void method2() {
		//业务逻辑实现
		System.out.println("ConcreteProduct1 业务逻辑");
	}


}


ConcreteProduct2.java 具体产品类

package com.jaynol.designpatterns.factorymethod;

public class ConcreteProduct2 extends Product{

	@Override
	public 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{

	@Override
	public <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{

	@Override
	protected Product createProduct() {
		/**
		 * 可在此处实现初始化的逻辑
		 */
		return new ConcreteProduct1();
	}

}

生产ConcreteProduct2的工厂:

package com.jaynol.designpatterns.factorymethod;

public class ConcreteProduct2Creator extends AbstractCreator{

	@Override
	protected 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();
		
	}

}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值