工厂模式定义了一个创建对象的接口,但由子类来确定要实例化哪个类。工厂方法让类把实例化推迟到子类
抽象工厂模式提供一个接口来创建相关或依赖对象的家族,而不需要指定具体类
1. 两种设计模式都属于创建型设计模式,目的是为了更好地创建对象。抽象工厂模式通过具体工厂类创建产品族,工厂模式通过具体创建者类创建单一产品。
2. 两者都隐藏了对象创建的细节,使得系统更加模块化,也降低了系统中各个类之间的耦合度,易于扩展和维护。
作用不同,工厂模式用于创建单一产品或一类产品,适用于产品种类单一或产品无复杂关联关系的场景。而抽象工厂模式通常用于更复杂的产品族,可以创建多个系列的产品,适用于产品组合多样化,且产品之间有关联或依赖关系的场景。
扩展性有区别,对于工厂模式来说创建新的产品相对简单,对于抽象工厂模式如果需要新增产品的话则需要修改抽象工厂以及每个子类的接口。
一个披萨连锁店需要在纽约和芝加哥建立门店,由于不同地区的饮食风格在对披萨的品类和原料的使用均有差异,所以需要系统在不同地区能够高效的提供不同的原料以及推荐针对地区风味的披萨。
对应披萨的不同种类可以对应为工厂模式中的产品,不同地区的门店视为对应的工厂,在这里可以使用工厂模式进行处理。而披萨中的原料可以理解为产品族,每个地区要提供不同的原料,每个披萨也会使用不同的原料,对应原料的供应可以使用抽象工厂进行处理。
Pizza父类和子类(产品)
public abstract class Pizza {
/**
* 名字
*/
String name;
/**
* 面团类型
*/
Dough dough;
/**
* 酱汁
*/
Sauce sauce;
abstract void prepare();
public String getName() {
return name;
}
void bake(){
System.out.println("350度烘焙24分钟。");
}
void cut(){
System.out.println("斜切成小块");
}
void box(){
System.out.println("放入普通包装");
}
}
public class NYStylePizza extends Pizza{
private PizzaIngredientFactory pizzaIngredientFactory;
public NYStylePizza(PizzaIngredientFactory pizzaIngredientFactory) {
this.pizzaIngredientFactory = pizzaIngredientFactory;
this.name = "纽约风味披萨";
}
@Override
void prepare() {
System.out.println("准备中..."+name);
dough = pizzaIngredientFactory.createDough();
System.out.println("加入"+dough.getName());
sauce= pizzaIngredientFactory.createSauce();
System.out.println("加入"+sauce.getName());
}
void bake(){
System.out.println("300度烘焙30分钟。");
}
}
public class ChicagoStylePizza extends Pizza{
private PizzaIngredientFactory pizzaIngredientFactory;
public ChicagoStylePizza( PizzaIngredientFactory pizzaIngredientFactory) {
this.pizzaIngredientFactory = pizzaIngredientFactory;
this.name = "芝加哥风味披萨";
}
@Override
void prepare() {
System.out.println("准备中..."+name);
dough = pizzaIngredientFactory.createDough();
System.out.println("加入"+dough.getName());
sauce= pizzaIngredientFactory.createSauce();
System.out.println("加入"+sauce.getName());
}
void box(){
System.out.println("芝加哥包装");
}
}
PizzaStore父类和子类(抽象创建者和具体创建者)
public abstract class PizzaStore {
public Pizza OrderPizza(String type){
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract Pizza createPizza(String type);
}
public class ChicagoPizzaStore extends PizzaStore{
@Override
protected Pizza createPizza(String type) {
Pizza pizza =null;
ChicagePizzaIngredientFactory chicagePizzaIngredientFactory = new ChicagePizzaIngredientFactory();
if (type.equals("ChicagoStyle")){
pizza = new ChicagoStylePizza(chicagePizzaIngredientFactory);
}else if(type.equals("pepperoni")){
//其他口味的
}else if(type.equals("clam")){
}
return pizza;
}
}
public class NYPizzaStore extends PizzaStore{
@Override
protected Pizza createPizza(String type) {
NYPizzaIngredientFactory nyPizzaIngredientFactory = new NYPizzaIngredientFactory();
Pizza pizza =null;
if (type.equals("NYStyle")){
pizza = new NYStylePizza(nyPizzaIngredientFactory);
}else if(type.equals("pepperoni")){
//其他口味的
}else if(type.equals("clam")){
}
return pizza;
}
}
Dough接口和实现(抽象产品和具体产品)
public interface Dough {
String getName();
}
public class NYDough implements Dough{
@Override
public String getName() {
return "纽约面团";
}
}
public class ChicagoDough implements Dough{
@Override
public String getName() {
return "芝加哥面团";
}
}
Sauce接口和实现(抽象产品和具体产品)
public interface Sauce {
String getName();
}
public class NYSauce implements Sauce{
@Override
public String getName() {
return "纽约酱汁";
}
}
public class ChicagoSauce implements Sauce{
@Override
public String getName() {
return "芝加哥酱汁";
}
}
PizzaIngredientFactory接口和实现(抽象工厂和具体工厂)
public interface PizzaIngredientFactory {
public Dough createDough();
public Sauce createSauce();
}
public class NYPizzaIngredientFactory implements PizzaIngredientFactory{
@Override
public Dough createDough() {
return new NYDough();
}
@Override
public Sauce createSauce() {
return new NYSauce();
}
}
public class ChicagePizzaIngredientFactory implements PizzaIngredientFactory{
@Override
public Dough createDough() {
return new ChicagoDough();
}
@Override
public Sauce createSauce() {
return new ChicagoSauce();
}
}
测试和结果
public class Test {
public static void main(String[] args) {
NYPizzaStore nyPizzaStore = new NYPizzaStore();
ChicagoPizzaStore chicagoPizzaStore = new ChicagoPizzaStore();
Pizza pizza = nyPizzaStore.OrderPizza("NYStyle");
System.out.println("订单:"+pizza.getName()+"已完成");
pizza = chicagoPizzaStore.OrderPizza("ChicagoStyle");
System.out.println("订单:"+pizza.getName()+"已完成");
}
}
准备中...纽约风味披萨
加入纽约面团
加入纽约酱汁
300度烘焙30分钟。
斜切成小块
放入普通包装
订单:纽约风味披萨已完成
准备中...芝加哥风味披萨
加入芝加哥面团
加入芝加哥酱汁
350度烘焙24分钟。
斜切成小块
芝加哥包装
订单:芝加哥风味披萨已完成
抽象工厂模式和工厂模式虽然有很多不同之处,但是并不影响这两个模式同时出现,抽象工厂的方法经常实现为工厂方法,在上面的案例中就表现出来了这点。抽象工厂的工作是定义一个接口,这个接口创建一组产品。这个接口的每个方法负责创建一个具体的产品,我们实现抽象工厂的子类,以提供这些实现,因此,在抽象工厂中,用工厂方法来实现生产方法是相当合理的方式。
在使用这两个设计模式需要首先要明确需求。如果需要处理一系列相关的产品并且希望它们能够一起工作,那么抽象工厂模式可能更适合。如果只需要创建一个产品或一类产品,那么工厂模式可能更合适。在添加新的产品或产品族时,尽量不要修改现有的代码,而是通过添加新的代码来扩展功能。