23个java设计模式(十一)-- 抽象工厂模式

2016年03月20日 原创
关键词: java 设计模式
摘要 抽象工厂模式提供一个创建一系列或相互依赖对象的接口,而无须指定他们具体的类。

一、概述。

抽象工厂模式提供一个创建一系列或相互依赖对象的接口,而无须指定他们具体的类。

设计某些系统时可能需要为用户提供一系列相关的对象,但系统不希望用户直接使用new运算符实例化这些对象,而是应当由系统来控制这些对象的创建,否则用户不仅要清楚地知道使用哪些类来创建这些对象,而且还必须要清楚这些对象之间是如何相关的,使得用户的代码和这些类形成紧耦合、缺乏弹性、不利于维护。

当系统准备为用户提供一系列相关的对象,又不想让用户代码和创建这些对象的类形成耦合时,就可以使用抽象工厂方法模式来设计系统。抽象工厂模式的关键是在一个抽象类或接口中定义若干个抽象方法,这些抽象方法分别返回某个类的实例,该抽象类或接口让其子类或实现该接口的类重写这些抽象方法为用户提供一系列相关的对象。

二、抽象工厂模式的结构。

工厂方法模式的结构中包括四种角色。

  • 抽象产品(Product):一个抽象类或接口,负责定义具体产品必须实现的方法。
  • 具体产品(ConcreteProduct):具体产品是一个类,如果Product是一个抽象类,那么具体产品是Product的子类;如果Product是一个接口,那么具体产品是实现Product接口的类。
  • 抽象工厂(AbstractFactory):一个接口或抽象类,负责定义若干个抽象方法。
  • 具体工厂(ConcreteFactory):如果抽象工厂是抽象类,具体工厂是抽象工厂的子类;如果抽象工厂是接口,具体工厂是实现抽象工厂的类。具体工厂重写了抽象工厂中的抽象方法,使该方法返回具体产品的实例。

三、示例程序。

抽象产品(Product)

public abstract class UpperClothes {
	public abstract int getChestSize();
	public abstract int getHeight();
	public abstract String getName();
}

public abstract class Trousers {
	public abstract int getWaistSize();
	public abstract int getHeight();
	public abstract String getName();
}

具体产品(ConcreteProduct)

public class CowboyUpperClothes extends UpperClothes{
	private int chestSize;
	private int height;
	private String name;
	
	public CowboyUpperClothes(int chestSize, int height, String name) {
		this.chestSize = chestSize;
		this.height = height;
		this.name = name;
	}

	@Override
	public int getChestSize() {
		return chestSize;
	}

	@Override
	public int getHeight() {
		return height;
	}

	@Override
	public String getName() {
		return name;
	}

}
public class CowboyTrousers extends Trousers{
	private int waistSize;
	private int height;
	private String name;
	
	public CowboyTrousers(int waistSize, int height, String name) {
		this.waistSize = waistSize;
		this.height = height;
		this.name = name;
	}

	@Override
	public int getWaistSize() {
		return waistSize;
	}

	@Override
	public int getHeight() {
		return height;
	}

	@Override
	public String getName() {
		return name;
	}

}
public class WesternUpperClothes extends UpperClothes{
	private int chestSize;
	private int height;
	private String name;
	
	public WesternUpperClothes(int chestSize, int height, String name) {
		this.chestSize = chestSize;
		this.height = height;
		this.name = name;
	}

	@Override
	public int getChestSize() {
		return chestSize;
	}

	@Override
	public int getHeight() {
		return height;
	}

	@Override
	public String getName() {
		return name;
	}
	
}
public class WesternTrousers extends Trousers{
	private int waistSize;
	private int height;
	private String name;
	
	public WesternTrousers(int waistSize, int height, String name) {
		this.waistSize = waistSize;
		this.height = height;
		this.name = name;
	}

	@Override
	public int getWaistSize() {
		return waistSize;
	}

	@Override
	public int getHeight() {
		return height;
	}

	@Override
	public String getName() {
		return name;
	}

}

抽象工厂(AbstractFactory)

public abstract class ClothesFactory {
	public abstract UpperClothes createUpperClothes(int chestSize, int height);
	public abstract Trousers createTrousers(int waistSize, int height);
}

具体工厂(ConcreteFactory)

public class ShanghaiClothesFactory extends ClothesFactory{

	@Override
	public UpperClothes createUpperClothes(int chestSize, int height) {
		return new CowboyUpperClothes(chestSize, height, "上海牌牛仔上衣");
	}

	@Override
	public Trousers createTrousers(int waistSize, int height) {
		return new CowboyTrousers(waistSize, height, "上海牌牛仔裤");
	}

}
public class BeijingClothesFactory extends ClothesFactory{

	@Override
	public UpperClothes createUpperClothes(int chestSize, int height) {
		return new WesternUpperClothes(chestSize, height, "北京牌西服上衣");
	}

	@Override
	public Trousers createTrousers(int waistSize, int height) {
		return new WesternTrousers(waistSize, height, "北京牌西服裤子");
	}

}

测试程序

public class Shop {
	UpperClothes clothes;
	Trousers trousers;
	public void setSuit(ClothesFactory factory, int chestSize, int waistSize, int height) {
		clothes = factory.createUpperClothes(chestSize, height);
		trousers = factory.createTrousers(waistSize, height);
		showMsg();
	}
	
	public void showMsg() {
		System.out.println("<套装信息>");
		System.out.println(clothes.getName()+":");
		System.out.println("胸围:"+clothes.getChestSize());
		System.out.println("身高:"+clothes.getHeight());
		System.out.println(trousers.getName()+":");
		System.out.println("腰围:"+trousers.getWaistSize());
		System.out.println("身高:"+trousers.getHeight());
	}
}
public class Example1Test {
	@Test
	public void testMain() {
		Shop shop = new Shop();
		ClothesFactory factory = new BeijingClothesFactory();
		shop.setSuit(factory, 110, 82, 170);
		factory = new ShanghaiClothesFactory();
		shop.setSuit(factory, 120, 88, 180);
	}
}

四、工厂方法模式的优点。

  1. 抽象工厂模式可以为用户创建一系列相关的对象,使用户和创建这些对象的类脱耦。
  2. 使用抽象工厂模式可以方便的为用户配置一系列对象。用户使用不同的具体工厂就能得到一组相关的对象,同时也能避免用户混用不同系列中的对象。
  3. 在抽象工厂模式中,可以随时增加“具体工厂”为用户提供一组相关的对象。

五、适合使用抽象工厂模式的情景。

  1. 系统需要为用户提供多个对象,但不希望用户直接使用new运算符实例化这些对象,即希望用户和创建对象的类脱耦。
  2. 系统需要为用户提供多个相关的对象,以便用户联合使用它们,但又不希望用户来决定这些对象是如何关联的。
  3. 系统需要为用户提供一系列对象,但只需要用户知道这些对象有哪些方法可用,不需要用户知道这些对象的创建过程。