简单工厂模式、工厂方法模式、抽象工厂模式,都是属于创建型设计模式。这三种设计模式,名字都包含“工厂”二字,如果没有认真地对它们的设计思想、代码进行认真比较,还真的很难区分出究竟是哪一种模式,很多开发者很容易混淆。

一、简单工厂模式

以鼠标为例,鼠标可以有多个生产厂家,不同的厂家鼠标的实现不同,工厂只有一个,我们只需要告诉工厂我们想要什么样的鼠标,就能生产什么鼠标。

鼠标接口

package design.factory.staticFac;

public interface Mouse {

	void sayHi();
}

鼠标接口的实现 

package design.factory.staticFac;

public class HPMouse implements Mouse {

	@Override
	public void sayHi() {
		System.out.println("HP Mouse");
	}

}
package design.factory.staticFac;

public class DellMouse implements Mouse {

	@Override
	public void sayHi() {
		System.out.println("Dell Mouse");
	}

}

鼠标生产工厂

package design.factory.staticFac;

public class MouseFactory {

	static Mouse getMouse(String producer) {
		switch(producer) {
		case "Dell": return new DellMouse();
		case "HP":return new HPMouse();
		default : return null;
		}
	}
}

 测试类

package design.factory.staticFac;

public class Test {

	public static void main(String[] args) {
		Mouse dellMouse = MouseFactory.getMouse("Dell");
		dellMouse.sayHi();
		Mouse hpMouse = MouseFactory.getMouse("HP");
		hpMouse.sayHi();
	}
}

测试结果

Dell Mouse
HP Mouse

缺点:如果想要新增产品的时候需要修改工厂代码,违背了开闭原则;这种模式的工厂不属于23设计模式之一

注:有些简单工厂利用反射Class.forName(clz.getName()).newInstance()实现的

static Mouse getMouse(Class cls) {
		try {
			Mouse mouse = (Mouse)Class.forName(cls.getName()).newInstance();
			return mouse;
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

 它也是一个具体的类,非接口 抽象类,好处是增加一种产品时,不需要修改getMouse()的代码。 缺点是效率相对较低,如果有参数相对麻烦,本身是类并非接口。

二、工厂方法模式

针对上述静态工厂方法的弊端,我们可以使用工厂方法模式解决;

Mouse接口以及实现类参考上面的代码;

工厂接口--工厂方法返回的是Mouse对象;

package design.factory.factoryMethod;

public interface MouseFactory {

	Mouse createMouse();
}

工厂实现--不同的工厂对应是不同的Mouse对象;

package design.factory.factoryMethod;

public class HPMouseFac implements MouseFactory {

	@Override
	public Mouse createMouse() {
		return new HPMouse();
	}

}

 

package design.factory.factoryMethod;

public class DellMouseFac implements MouseFactory {

	@Override
	public Mouse createMouse() {
		return new DellMouse();
	}

}

测试类

package design.factory.factoryMethod;

public class Test {

	public static void main(String[] args) {
		MouseFactory hpMouseFac = new HPMouseFac();
		Mouse hpMouse = hpMouseFac.createMouse();
		hpMouse.sayHi();
		
		MouseFactory dellMouseFac = new DellMouseFac();
		Mouse dellMouse = dellMouseFac.createMouse();
		dellMouse.sayHi();
	}
}

测试结果:

HP Mouse
Dell Mouse
 

工厂方法模式的优点在于当新增产品的时候不需要修改已有的工厂代码,新增新产品的工厂实现以及产品的实现,即可在客户端调用,扩展性好,适合产品比较少的情况

三、抽象工厂模式

抽象工厂模式是为了更好地适应产品的多元化,当产品不止有鼠标还有键盘等其他产品时;如果还使用工厂方法模式,就要建立键盘工厂,键盘工厂实现,键盘接口,键盘实现;产品越多类越多,对于我们的工程就显得比较臃肿,这种情况使用抽象工厂模式;

键盘Keybo接口

package design.factory.abstractFac;

public interface Keybo {
	void sayHi();
}

键盘实现

package design.factory.abstractFac;

public class DellKeybo implements Keybo {

	@Override
	public void sayHi() {
		System.out.println("Dell Keybo");

	}

}
package design.factory.abstractFac;

public class HPKeybo implements Keybo {

	@Override
	public void sayHi() {
		System.out.println("HP Keybo");

	}

}

 工厂接口

package design.factory.abstractFac;

public interface Factory {

	Mouse createMouse();
	Keybo createKeybo();
}

工厂接口实现

package design.factory.abstractFac;

public class HPFac implements Factory {

	@Override
	public Mouse createMouse() {
		return new HPMouse();
	}

	@Override
	public Keybo createKeybo() {
		return new HPKeybo();
	}

}
package design.factory.abstractFac;

public class DellFac implements Factory {

	@Override
	public Mouse createMouse() {
		return new DellMouse();
	}

	@Override
	public Keybo createKeybo() {
		return new DellKeybo();
	}

}

测试类

package design.factory.abstractFac;

public class Test {

	public static void main(String[] args) {
		Factory hpFac = new HPFac();
		Mouse hpMouse = hpFac.createMouse();
		Keybo hpKeybo = hpFac.createKeybo();
		hpMouse.sayHi();
		hpKeybo.sayHi();


		Factory dellFac = new DellFac();
		Mouse dellMouse = dellFac.createMouse();
		Keybo dellKeybo = dellFac.createKeybo();
		dellMouse.sayHi();
		dellKeybo.sayHi();
	}
}

测试结果

HP Mouse
HP Keybo
Dell Mouse
Dell Keybo
 

如果添加厂家只需要添加三个接口的实现就可以了

添加华硕厂家

华硕工厂

package design.factory.abstractFac;

public class AsusFac implements Factory {

	@Override
	public Mouse createMouse() {
		return new AsusMouse();
	}

	@Override
	public Keybo createKeybo() {
		return new AsusKeybo();
	}

}

华硕键盘 

package design.factory.abstractFac;

public class AsusKeybo implements Keybo {

	@Override
	public void sayHi() {
		System.out.println("Asus Keybo");

	}

}

华硕鼠标

package design.factory.abstractFac;

public class AsusMouse implements Mouse {

	@Override
	public void sayHi() {
		System.out.println("Asus Mouse");
	}

}

测试类

package design.factory.abstractFac;

public class Test {

	public static void main(String[] args) {
		Factory hpFac = new HPFac();
		Mouse hpMouse = hpFac.createMouse();
		Keybo hpKeybo = hpFac.createKeybo();
		hpMouse.sayHi();
		hpKeybo.sayHi();


		Factory dellFac = new DellFac();
		Mouse dellMouse = dellFac.createMouse();
		Keybo dellKeybo = dellFac.createKeybo();
		dellMouse.sayHi();
		dellKeybo.sayHi();
		
		Factory asusFac = new AsusFac();
		Mouse asusMouse = asusFac.createMouse();
		Keybo asusKeybo = asusFac.createKeybo();
		asusMouse.sayHi();
		asusKeybo.sayHi();
	}
}

测试结果

HP Mouse
HP Keybo
Dell Mouse
Dell Keybo
Asus Mouse
Asus Keybo
 

当产品类型比较多,比较多元化,产品的生产方式一致的时候适合使用抽象工厂模式

缺点是当新增产品的时候需要修改接口和接口实现,但是新增工厂的时候只需要实现接口就可以了

 

更多推荐