Java模式之工厂模式

一般理解,工厂就是批量生产某种东西的地方,相对的,Java中的工厂模式就是创建对象的地方,是创建类模式中的一种。它解决的主要问题就是将“对象的创建逻辑与操作对象的业务逻辑分离解耦”,分别在不同的地方实现,而不是混杂在一起,目的是提供更清晰更容易扩展的代码。

工厂模式有简单工厂、方法工厂、抽象工厂三类。

1、简单工厂模式

简单工厂模式适用于生产的“产品”种类很少,只需要提供一种工厂的场景。假设有如下场景,首先有一个关于面条的接口:

// 面条接口
interface Noodle {
	public void say();
}

现在有两种具体的面条:

// 拉面
class HandPulledNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am hand-pulled noodles");	
	}
	
}
// 方便面
class InstantNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am instant noodles");
	}
}

接下来根据程序的输入条件创建不同的面条,在不使用工厂模式的情况下,全部代码如下:

// 面条接口
interface Noodles {
	public void say();
}

// 拉面
class HandPulledNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am hand-pulled noodles");	
	}
	
}
// 方便面
class InstantNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am instant noodles");
	}
}

public class SimpleFactory {

	public static void main(String[] args) {
		Noodles n = null;
		// 创建逻辑
		if (args[0].equalsIgnoreCase("HandPulled")) {
			n = new HandPulledNoodles();
		} else if (args[0].equalsIgnoreCase("Instant")) {
			n = new InstantNoodles();
		}
		// 业务逻辑
		if (n != null) {
			n.say();
		} else {
			System.out.println("Parameter error");
		}
	}

}

可以看到面条的创建逻辑与业务逻辑混合在一起,如果想新增加一种新面条,如意大利面,则需要修改main方法。接下来使用简单工厂模式,将创建逻辑与业务逻辑分离,代码如下:

// 面条接口
interface Noodles {
	public void say();
}

// 拉面
class HandPulledNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am hand-pulled noodles");
	}

}

// 方便面
class InstantNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am instant noodles");
	}
}

// 面条工厂
class NoodlesFactory {
	public static Noodles create(String type) {
		// 创建逻辑
		if (type.equalsIgnoreCase("HandPulled")) {
			return new HandPulledNoodles();
		} else if (type.equalsIgnoreCase("Instant")) {
			return new InstantNoodles();
		} else {
			return null;
		}
	}
}

public class SimpleFactory {

	public static void main(String[] args) {
		Noodles n = NoodlesFactory.create(args[0]);
		// 业务逻辑
		if (n != null) {
			n.say();
		} else {
			System.out.println("Parameter error");
		}
	}

}

可以看到,已经将创建逻辑转移到工厂类中。在main方法中,只是根据启动参数调用工厂类的静态方法创建面条实例。创建什么类型的面条由启动参数决定,main方法不需要知道具体的面条类型,这就实现了创建与业务的分离解耦,具有更好的扩展性。假如新增加一种意大利面,则只需要新定义一种面条,然后修改工厂类的实现,而main中的业务逻辑则不需要修改,代码如下:

// 面条接口
interface Noodles {
	public void say();
}

// 拉面
class HandPulledNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am hand-pulled noodles");
	}

}

// 方便面
class InstantNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am instant noodles");
	}
}

// 意大利面
class PastaNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am instant noodles");
	}
}

// 面条工厂
class NoodlesFactory {
	public static Noodles create(String type) {
		// 创建逻辑
		if (type.equalsIgnoreCase("HandPulled")) {
			return new HandPulledNoodles();
		} else if (type.equalsIgnoreCase("Instant")) {
			return new InstantNoodles();
		} else if (type.equalsIgnoreCase("Pasta")) {
			return new PastaNoodles();
		}
		else {
			return null;
		}
	}
}

public class SimpleFactory {

	public static void main(String[] args) {
		Noodles n = NoodlesFactory.create(args[0]);
		// 业务逻辑
		if (n != null) {
			n.say();
		} else {
			System.out.println("Parameter error");
		}
	}

}

2、方法工厂模式

方法工厂模式与简单工厂模式实现方式基本一样,它只是对简单工厂模式的一种扩展。解决的问题是当产品的各类太多时,我们可以提供多种不同的工厂分别生产,不同的工厂类都实现同样的工厂接口。

首先对上例中面条的种类进行扩展,提供加牛肉的面条(修饰器模式),注意这不是水平扩展而是垂直扩展。修改后的代码:

// 面条接口
interface Noodles {
	public void say();
}

// 加了牛肉的面条
class BeefNoodles implements Noodles {
	private Noodles commonNoodles;

	public BeefNoodles(Noodles noodles) {
		commonNoodles = noodles;
	}

	@Override
	public void say() {
		commonNoodles.say();
		System.out.println("Add beef");
	}
}

// 拉面
class HandPulledNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am hand-pulled noodles");
	}

}

// 方便面
class InstantNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am instant noodles");
	}
}

// 意大利面
class PastaNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am instant noodles");
	}
}

// 面条工厂接口
interface NoodlesFactory {
	public Noodles create(String type);
}

// 普通面条工厂
class ComNoodlesFactory implements NoodlesFactory {
	public Noodles create(String type) {
		// 创建逻辑
		if (type.equalsIgnoreCase("HandPulled")) {
			return new HandPulledNoodles();
		} else if (type.equalsIgnoreCase("Instant")) {
			return new InstantNoodles();
		} else if (type.equalsIgnoreCase("Pasta")) {
			return new PastaNoodles();
		} else {
			return null;
		}
	}
}

// 牛肉面条工厂
class BeefNoodlesFactory implements NoodlesFactory {
	public Noodles create(String type) {
		// 创建逻辑
		if (type.equalsIgnoreCase("HandPulled")) {
			return new BeefNoodles(new HandPulledNoodles());
		} else if (type.equalsIgnoreCase("Instant")) {
			return new BeefNoodles(new InstantNoodles());
		} else if (type.equalsIgnoreCase("Pasta")) {
			return new BeefNoodles(new PastaNoodles());
		} else {
			return null;
		}
	}
}

public class MethodFactory {

	public static void main(String[] args) {
		// 创建工厂
		NoodlesFactory nFactory = null;
		if (args[0].equalsIgnoreCase("y")) {
			nFactory = new BeefNoodlesFactory();
		} else {
			nFactory = new ComNoodlesFactory();
		}
		// 生产面条
		Noodles n = nFactory.create(args[1]);
		// 业务逻辑
		if (n != null) {
			n.say();
		} else {
			System.out.println("Parameter error");
		}
	}

}

可以看到,通过修饰器模式,我们新增加了一大类面条,加牛肉的面条。相应的,也提交了两种类型的面条工厂,一种生产普通面条,一种生产加了牛肉的面条。

这种方法的缺点是当面条的种类很多时,如加辣椒的面条、加醋的面条时,需要对每种面条都提供相应的工厂类实现。另外在main方法中也就是业务逻辑中,与具体的工厂类产生了耦合,不利于代码的扩展。想当然的,我们可以把创建工厂的逻辑也转移出去,搞一个创建工厂的工厂,暂时把它理解成“抽象工厂”模式,我不知道这样理解是否正确。

3、抽象工厂模式

上述代码将创建工厂的逻辑与业务逻辑混合在一起了,继续分离,代码如下:
 

// 面条接口
interface Noodles {
	public void say();
}

// 加了牛肉的面条
class BeefNoodles implements Noodles {
	private Noodles commonNoodles;

	public BeefNoodles(Noodles noodles) {
		commonNoodles = noodles;
	}

	@Override
	public void say() {
		commonNoodles.say();
		System.out.println("Add beef");
	}
}

// 拉面
class HandPulledNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am hand-pulled noodles");
	}

}

// 方便面
class InstantNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am instant noodles");
	}
}

// 意大利面
class PastaNoodles implements Noodles {

	@Override
	public void say() {
		System.out.println("I am instant noodles");
	}
}

// 面条工厂接口
interface NoodlesFactoryInf {
	public Noodles create(String type);
}

// 面条工厂实现
abstract class NoodlesFactory {
	// 私有静态内部类:普通面条工厂
	private static class ComNoodlesFactory implements NoodlesFactoryInf {
		public Noodles create(String type) {
			// 创建逻辑
			if (type.equalsIgnoreCase("HandPulled")) {
				return new HandPulledNoodles();
			} else if (type.equalsIgnoreCase("Instant")) {
				return new InstantNoodles();
			} else if (type.equalsIgnoreCase("Pasta")) {
				return new PastaNoodles();
			} else {
				return null;
			}
		}
	}

	// 私有静态内部类:牛肉面条工厂
	private static class BeefNoodlesFactory implements NoodlesFactoryInf {
		public Noodles create(String type) {
			// 创建逻辑
			if (type.equalsIgnoreCase("HandPulled")) {
				return new BeefNoodles(new HandPulledNoodles());
			} else if (type.equalsIgnoreCase("Instant")) {
				return new BeefNoodles(new InstantNoodles());
			} else if (type.equalsIgnoreCase("Pasta")) {
				return new BeefNoodles(new PastaNoodles());
			} else {
				return null;
			}
		}
	}

	public static NoodlesFactoryInf createFactory(String kind) {
		if (kind.equalsIgnoreCase("Beef")) {
			return new BeefNoodlesFactory();
		} else {
			return new ComNoodlesFactory();
		}
	}
}

public class MethodFactory {

	public static void main(String[] args) {
		// 生产面条
		Noodles n = NoodlesFactory.createFactory(args[0]).create(args[1]);
		// 业务逻辑
		if (n != null) {
			n.say();
		} else {
			System.out.println("Parameter error");
		}
	}

}

上例中的工厂类实现是抽象类,用户不能也不需要实例化这个类。工厂类中包含私有内部静态类,负责生产具体种类的面条。main方法中不需要关心有多少种面条,有多少种面条工厂,只需要调用静态方法并传递参数就可以了。

另外如果新增加了一种面条,除了新的面条类本身,只需要修改工厂类实现中的普通面条的内部静态类。如果新增加了另外一大类面条,如加辣椒,则除了加辣椒这个类本身外,只需要在工厂类实现中新增加静态内部类并为createFactory新加一个分支就可以了。这是一种比较理解的工厂模式实现方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值