《Head First 设计模式》:抽象工厂模式

本贴最后更新于 1609 天前,其中的信息可能已经时过境迁

正文

一、定义

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

要点:

  • 抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产品的具体产品是什么。这样一来,客户就从具体的产品中被解耦。
  • 抽象工厂的任务是定义一个负责创建一组产品的接口。这个接口内的每个方法都负责创建一个产品,同时利用实现抽象工厂的子类来提供具体的做法。
  • 抽象工厂的方法经常以工厂方法的方式实现。

二、实现步骤

1、创建产品抽象类

(1)产品 A 抽象类

/**
 * 产品A抽象类
 */
public abstract class ProductA {
    
    String name;
    
    public String getName() {
        return name;
    }
}

(2)产品 B 抽象类

/**
 * 产品B抽象类
 */
public abstract class ProductB {
    
    String name;
    
    public String getName() {
        return name;
    }
}

2、创建具体的产品,并继承产品抽象类

(1)产品 A1

/**
 * 产品A1
 */
public class ConcreteProductA1 extends ProductA {
    
    public ConcreteProductA1() {
        name = "ConcreteProductA1";
    }
}

(2)产品 A2

/**
 * 产品A2
 */
public class ConcreteProductA2 extends ProductA {
    
    public ConcreteProductA2() {
        name = "ConcreteProductA2";
    }
}

(3)产品 B1

/**
 * 产品B1
 */
public class ConcreteProductB1 extends ProductB {
    
    public ConcreteProductB1() {
        name = "ConcreteProductB1";
    }
}

(4)产品 B2

/**
 * 产品B2
 */
public class ConcreteProductB2 extends ProductB {
    
    public ConcreteProductB2() {
        name = "ConcreteProductB2";
    }
}

3、创建工厂接口,并定义创建产品的方法

也可以使用工厂抽象类,然后在创建具体工厂时继承工厂抽象类。

/**
 * 抽象工厂接口
 */
public interface AbstractFactory {
    
    /**
     * 创建产品A
     */
    public ProductA createProductA();
    
    /**
     * 创建产品B
     */
    public ProductB createProductB();
}

4、创建具体的工厂,并实现工厂接口

(1)工厂 1

/**
 * 工厂1
 */
public class ConcreteFactory1 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new ConcreteProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new ConcreteProductB1();
    }
}

(2)工厂 2

/**
 * 工厂2
 */
public class ConcreteFactory2 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new ConcreteProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new ConcreteProductB2();
    }
}

5、使用工厂创建产品

public class Test {
    
    public static void main(String[] args) {
        // 工厂1
        AbstractFactory factory1 = new ConcreteFactory1();
        // 工厂2
        AbstractFactory factory2 = new ConcreteFactory2();
        
        // 工厂1创建产品
        ProductA productA = factory1.createProductA();
        System.out.println("工厂1创建产品A:" + productA.getName());
        ProductB productB = factory1.createProductB();
        System.out.println("工厂1创建产品B:" + productB.getName());
        // 工厂2创建产品
        productA = factory2.createProductA();
        System.out.println("工厂2创建产品A:" + productA.getName());
        productB = factory2.createProductB();
        System.out.println("工厂2创建产品B:" + productB.getName());
    }
}

三、举个栗子

1、背景

假设你有一个披萨店,并且拥有许多加盟店。为了确保每家加盟店都能使用高质量的原料,你打算建造生产原料的工厂,并将原料运送到各家加盟店。

由于加盟店坐落在不同的区域,每个区域的原料是不一样的。因此,必须能够针对不同的区域提供相应的原料。

2、实现

为每个区域建造一个工厂,每个工厂负责创建相应区域的原料。

(1)创建所有原料抽象类

/**
 * 面团抽象类
 */
public abstract class Dough {
    
    String name;
    
    public String getName() {
        return name;
    }
}
/**
 * 酱料抽象类
 */
public abstract class Sauce {
    
    String name;
    
    public String getName() {
        return name;
    }
}
/**
 * 芝士抽象类
 */
public abstract class Cheese {
    
    String name;
    
    public String getName() {
        return name;
    }
}

(2)创建不同区域的所有原料

/**
 * 薄皮面团
 */
public class ThinCrustDough extends Dough {
    
    public ThinCrustDough() {
        name = "Thin Crust Dough";
    }
}
/**
 * 厚皮面团
 */
public class ThickCrustDough extends Dough {

    public ThickCrustDough() {
        name = "Thick Crust Dough";
    }
}
/**
 * 大蒜番茄酱
 */
public class MarinaraSauce extends Sauce {

    public MarinaraSauce() {
        name = "Marinara Sauce";
    }
}
/**
 * 番茄酱
 */
public class PlumTomatoSauce extends Sauce {

    public PlumTomatoSauce() {
        name = "Plum Tomato Sauce";
    }
}
/**
 * 帕马森雷加诺干酪
 */
public class ReggianoCheese extends Cheese{
    
    public ReggianoCheese() {
        name = "Reggiano Cheese";
    }
}
/**
 * 马苏里拉奶酪
 */
public class MozzarellaCheese extends Cheese{

    public MozzarellaCheese() {
        name = "Mozzarella Cheese";
    }
}

(3)创建原料工厂接口

/**
 * 披萨原料工厂接口
 */
public interface PizzaIngredientFactory {
    
    /**
     * 创建面团
     */
    public Dough createDough();
    
    /**
     * 创建酱料
     */
    public Sauce createSauce();
    
    /**
     * 创建芝士
     */
    public Cheese createCheese();
    
    // 创建其他原料
}

(4)创建不同区域的原料工厂

/**
 * 纽约原料工厂
 */
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {

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

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

    @Override
    public Cheese createCheese() {
        return new ReggianoCheese();
    }
}
/**
 * 芝加哥原料工厂
 */
public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {

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

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

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

(5)使用不同区域的原料工厂创建原料

public class Test {
    
    public static void main(String[] args) {
        // 纽约原料工厂
        PizzaIngredientFactory nyFactory = new NYPizzaIngredientFactory();
        // 芝加哥原料工厂
        PizzaIngredientFactory chicagoFactory = new ChicagoPizzaIngredientFactory();
        
        // 使用纽约原料工厂创建原料
        Dough dough = nyFactory.createDough();
        Sauce sauce = nyFactory.createSauce();
        Cheese cheese = nyFactory.createCheese();
        System.out.println("New York Pizza Ingredient Factory Create:");
        System.out.println(" " + dough.getName());
        System.out.println(" " + sauce.getName());
        System.out.println(" " + cheese.getName() + "\n");
        // 使用芝加哥原料工厂创建原料
        dough = chicagoFactory.createDough();
        sauce = chicagoFactory.createSauce();
        cheese = chicagoFactory.createCheese();
        System.out.println("Chicago Pizza Ingredient Factory Create:");
        System.out.println(" " + dough.getName());
        System.out.println(" " + sauce.getName());
        System.out.println(" " + cheese.getName());
    }
}
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...