设计模式:抽象工厂模式

目录

 

概述

解决问题

代码实现

visio图


概述

  抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。可以理解成是多个工厂方法的组合。

解决问题

  在工厂方法模式中,我们的具体创建者每次使用都只能创建一个同类型的对象,假如我们现在需要的是多个不同类型的对象,工厂方法就满足不了需求了。这时我们可以把多个工厂方法组合到一个类,这就是抽象工厂模式,它就是专门用来创建多个产品,也可以说是创建产品家族的。

代码实现

原料产品族(只给出示范代码,更多请自己实现)

/**
 * 奶酪
 * @author Mr.Li
 *
 */
public class Cheese {

}
/**
 * 面团
 * @author Mr.Li
 *
 */
public class Dough {

}

public class ReggianoCheese extends Cheese {

}
public class ThinCrustDough extends Dough{

}

创建抽象工厂

/**
 * 创建一个原料工厂。该工厂为抽象工厂,负责创建所有的原料。
 * @author Mr.Li
 *
 */
public interface PizzaIngredientFactory {
	 /*
	 * 在接口中,每个原料都有一个对应的方法创建该原料
	 */
	public Dough createDough();

	public Sauce createSauce();

	public Cheese createCheese();

	public Veggies[] createVeggies();

	public Pepperoni createPepperoni();

	public Clams createClams();	
	
}

工厂实现

/**
 * 原料工厂创建完成之后,需要创建具体的原料工厂。该具体工厂只需要继承PizzaIngredientFactory,然后实现里面的方法即可。
 * @author Mr.Li
 *
 */
public class NYPizzaIngredientFactory implements PizzaIngredientFactory{

	@Override
	public Cheese createCheese() {
		return new ReggianoCheese();
	}

	@Override
	public Clams createClams() {
		return new FreshClams();
	}

	@Override
	public Dough createDough() {
		return new ThinCrustDough();
	}

	@Override
	public Pepperoni createPepperoni() {
		return new SlicedPepperoni();
	}

	@Override
	public Sauce createSauce() {
		return new MarinaraSauce();
	}

	@Override
	public Veggies[] createVeggies() {
		Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RefPepper() };
		return veggies;
	}

}

pizza类

/**
 * 披萨类里面,我们需要使用原料,其他方法保持不变,将prepare()方法声明为抽象,在这个方法中,我们需要收集披萨所需要的原料。
 * @author Mr.Li
 *
 */
public abstract class Pizza {
	/*
	 * 每个披萨都持有一组在准备时会用到的原料
	 */
	String name;
	Dough dough;
	Sauce sauce;
	Veggies veggies[];
	Cheese cheese;
	Pepperoni pepperoni;
	Clams clams;

	/*
	 * prepare()方法声明为抽象方法。在这个方法中,我们需要收集披萨所需要的原料,而这些原料都是来自原料工厂
	 */
	public abstract void prepare();

	public void bake() {
		System.out.println("Bake for 25 munites at 350");
	}

	public void cut() {
		System.out.println("Cutting the pizza into diagonal slices");
	}

	public void box() {
		System.out.println("Place pizza in official PizzaStore box");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
    }
}
/**
 * Pizza的代码利用相关的工厂生产原料。所生产的原料依赖所使用的工厂,
 * Pizza类根本不关心这些原料,它只需要知道如何制作披萨即可。这里,Pizza和区域原料之间被解耦。
 * @author Mr.Li
 *
 */
public class CheesePizza extends Pizza{
	PizzaIngredientFactory ingredientFactory;

	/*
	 * 要制作披萨必须要有制作披萨的原料,而这些原料是从原料工厂运来的
	 */
	public CheesePizza(PizzaIngredientFactory ingredientFactory) {
		this.ingredientFactory = ingredientFactory;
	}

	/*
	 * 实现prepare方法 prepare 方法一步一步地创建芝士比萨,每当需要原料时,就跟工厂要
	 */
	public void prepare() {
		System.out.println("Prepareing " + name);
		dough = ingredientFactory.createDough();
		sauce = ingredientFactory.createSauce();
		cheese = ingredientFactory.createCheese();
	}

 }
public class ClamPizza extends Pizza {

	PizzaIngredientFactory ingredientFactory;

	public ClamPizza(PizzaIngredientFactory ingredientFactory) {
		this.ingredientFactory = ingredientFactory;
	}

	@Override
	public void prepare() {
		System.out.println("Prepare " + name);
		dough = ingredientFactory.createDough();
		sauce = ingredientFactory.createSauce();
		cheese = ingredientFactory.createCheese();
		clams = ingredientFactory.createClams();
	}

}

商店

/**
 * 商店抽象
 * @author Mr.Li
 *
 */
public abstract class PizzaStore {
	public Pizza orderPizza(String type){
		Pizza pizza;
		pizza = createPizza(type);

		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();

		return pizza;
	}

	/*
	 * 创建pizza的方法交给子类去实现
	 */
     abstract Pizza createPizza(String type);
}
/**
 * 在披萨店中,我们依然需要关注原料,当地的披萨店需要和本地的原料工厂关联起来。
 * @author Mr.Li
 *
 */
public class NYPizzaStore extends PizzaStore{
	@Override
	Pizza createPizza(String type) {
		Pizza pizza = null;
		// 使用纽约的原料工厂
		PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
		if ("cheese".equals(type)) {
			pizza = new CheesePizza(ingredientFactory);
			pizza.setName("New York Style Cheese Pizza");
		}else if ("clam".equals(type)) {
			pizza = new ClamPizza(ingredientFactory);
			pizza.setName("New York Style Clam Pizza");
		}
		return pizza;
	}
}

调用

	public static void main(String[] args) {
		NYPizzaStore nyPizzaStore =  new NYPizzaStore();
		nyPizzaStore.orderPizza("cheese");
	}

visio图

优缺点及使用场景

	/**
	 * 优点:	1、  抽象工厂隔离了具体类的生成,是的客户端不需要知道什么被创建。所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
	 * 		2、  当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。
	 * 缺点:	1、添加新的行为时比较麻烦。如果需要添加一个新产品族对象时,需要更改接口及其下所有子类,这必然会带来很大的麻烦。
	 * 使用场景:	1. 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
	 * 			2. 系统中有多于一个的产品族,而每次只使用其中某一产品族。
	 * 			3. 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
	 * 			4. 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

	 */

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值