工厂模式

背景-茶店点餐系统

设计一个茶类(Tea),并定义两个子类:红茶(RedTea)和绿茶(GreenTea),还有茶店类,茶店类(TeaStore)具有下单茶品的功能。

@Data
public abstract class Tea {

    public abstract String getName();

    public abstract void addSugar();

    public abstract void addMilk();
}
public class RedTea extends Tea{

    @Override
    public String getName() {
        return "红茶";
    }

    @Override
    public void addSugar() {
        System.out.println(getName() + "加糖");
    }

    @Override
    public void addMilk() {
        System.out.println(getName() + "加奶");
    }
}
public class GreenTea extends Tea{

    @Override
    public String getName() {
        return "绿茶";
    }

    @Override
    public void addSugar() {
        System.out.println(getName() + "加糖");
    }

    @Override
    public void addMilk() {
        System.out.println(getName() + "加奶");
    }
}
public class TeaStore {
    // Tea和TeaStore耦合
    public Tea orderTea(String type){
        if(StringUtils.equals(type, "red")){
            return new RedTea();
        }else if(StringUtils.equals(type, "green")){
            return new GreenTea();
        }else{
            throw new RuntimeException("type error");
        }
    }
}
public class Client {

    public static void main(String[] args) {
        TeaStore teaStore = new TeaStore();
        Tea red = teaStore.orderTea("red");
        System.out.println(red.getName());
    }
}

简单工厂模式

注意简单工厂模式不属于GOF中23种经典设计模式

角色

  • 抽象产品:定义产品规范,描述产品主要特性和功能;
  • 具体产品:实现或者继承抽象产品的子类;
  • 具体工厂:提供了创建产品的方法,调用者通过该方法来获取产品。

实现

非静态实现
public class TeaFactory {

    public Tea creatTea(String type){
        if(StringUtils.equals(type, "red")){
            return new RedTea();
        }else if(StringUtils.equals(type, "green")){
            return new GreenTea();
        }else{
            throw new RuntimeException("type error");
        }
    }
}
静态实现
public class StaticTeaFactory {
    public static Tea creatTea(String type){
        if(StringUtils.equals(type, "red")){
            return new RedTea();
        }else if(StringUtils.equals(type, "green")){
            return new GreenTea();
        }else{
            throw new RuntimeException("type error");
        }
    }
}
拓展实现(利用配置文件进行解耦)

tea.properties文件内容

redTea=com.learn.demo7_factory.simpleFactory.RedTea
greenTea=com.learn.demo7_factory.simpleFactory.GreenTea
public class ExtentTeaFactory {

    private static Map<String, Tea> teaMap = new HashMap();

    static {
        Properties p = new Properties();
        InputStream in = ExtentTeaFactory.class.getClassLoader().getResourceAsStream("tea.properties");
        try {
            p.load(in);
            Set<String> keys = p.stringPropertyNames();
            for(String key : keys) {
                String className = p.getProperty(key);
                Class clazz = Class.forName(className);
                Tea tea = (Tea) clazz.newInstance();
                teaMap.put(key, tea);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Tea createTea(String type) {
        return teaMap.get(type);
    }
}
public class TeaStore {

    public Tea orderTea(String type){
        // 1 非静态
        TeaFactory teaFactory = new TeaFactory();
        Tea tea = teaFactory.creatTea(type);
        // 2 静态
        // Tea tea2 = StaticTeaFactory.creatTea(type);
        // 3 拓展简单工厂模式
        // Tea tea3 = ExtentTeaFactory.createTea(type);
        return tea;
    }
}
public class Client {
    public static void main(String[] args) {
        TeaStore teaStore = new TeaStore();
        Tea red = teaStore.orderTea("red");
        red.addMilk();
        red.addSugar();
    }
}

优缺点

  • 优点
    • 封装创建对象的过程,通过参数直接获取对象;
    • 分开对象的创建和业务逻辑层,避免修改客户代码,实现新产品直接修改工厂类,无需修改原代码。
  • 缺点
    • 增加新产品需要修改工厂类的代码,违背“开闭原则”。

工厂方法模式

概念

定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。

角色

  • 抽象工厂:提供创建产品的接口;
  • 具体工厂:实现抽象工厂中的抽象方法,完成具体产品的创建;
  • 抽象产品:定义产品的规范,描述产品的主要特性和功能;
  • 具体产品:实现抽象产品角色定义的接口,由具体工厂创建,与具体工厂一一对应;

实现

抽象工厂

public abstract class TeaFactory {

    public abstract Tea getTea();
}

具体工厂

public class RedTeaFactory extends TeaFactory {

    @Override
    public Tea getTea() {
        return new RedTea();
    }
}
public class GreenTeaFactory extends TeaFactory{

    @Override
    public Tea getTea() {
        return new GreenTea();
    }
}
@Data
public class TeaStore {

    private TeaFactory teaFactory;

    public Tea orderTea(){
        Tea tea = teaFactory.getTea();
        tea.addMilk();
        tea.addSugar();
        return tea;
    }
public class Client {
    public static void main(String[] args) {
        TeaStore teaStore = new TeaStore();
        teaStore.setTeaFactory(new GreenTeaFactory());
        teaStore.orderTea();
    }
}

优缺点

  • 优点
    • 系统新增产品时,只需要新增具体产品类及其对应的具体工厂类,无需修改原工厂,满足开闭原则
  • 缺点
    • 每新增一个产品就需要新增一个具体产品类和具体的产品工厂类,增加了系统的复杂度。

抽象工厂模式

工厂方法模式中考虑的是一类产品的生产,如电视机厂只生产电视机,电脑厂只生产电脑。这些工厂只生产同种类产品,同种类产品称为同等级产品,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级的产品。比如小米既生产手机,也生产汽车。

抽象工厂模式则考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族。比如座机、手机属于同一产品等级,台式电脑、笔记本属于同一产品等级;座机、台式电脑属于同一产品族,手机、笔记本属于同一产品族。定义抽象工厂完成同一产品族产品的创建。

概念

为访问类提供一个创建一组相关或者相互依赖对象的接口,且访问无须指定所要产品的具体类就能够得到不同等级产品的模式结构。抽象工厂模式是工厂方法模式的升级版,工厂模式方法只生产一个等级的产品,抽象工厂模式可生产多个等级的产品。

角色

  • 抽象工厂:提供创建产品接口,包含创建多个产品的方法,可以创建多个不同等级的商品;
  • 具体工厂:实现抽象工厂中的多个抽象方法。完成具体产品的创建;
  • 抽象产品:定义产品的规范,描述产品的主要特性和功能,抽象工厂模式有多个抽象产品;
  • 具体产品:实现抽象产品定义的接口,由具体共厂创建,同具体工厂是一对一的关系。

实现

抽象产品

public abstract class Cake {

    abstract String getDescription();
}

具体产品

public class RedCake extends Cake {

    @Override
    String getDescription() {
        return "红蛋糕";
    }
}
public class GreenCake extends Cake {
    @Override
    String getDescription() {
        return "绿蛋糕";
    }
}

抽象工厂

public abstract class CakeFactory {
		
  	// 产品1
    abstract Tea creatTea();
		
  	// 产品2
    abstract Cake crateCake();
}

具体工厂

public class RedCakeFactory extends CakeFactory{
    @Override
    Tea creatTea() {
        return new RedTea();
    }

    @Override
    Cake crateCake() {
        return new RedCake();
    }
}
public class GreenCakeFactory extends CakeFactory{
    @Override
    Tea creatTea() {
        return new GreenTea();
    }

    @Override
    Cake crateCake() {
        return new GreenCake();
    }
}

优缺点

  • 优点
    • 产品族中多个对象被设计成一起工作时,保证客户端只使用同一产品族中对象
  • 缺点
    • 产品族中增加新产品时,所有工厂类都需要修改

Java中实例

  • Collection接口是抽象工厂类
  • ArrayList是具体的工厂类
  • Iterator接口是抽象商品类
  • ArrayList类中的Iter内部类是具体的商品类

在具体的工厂类ArrayList中iterator()方法创建具体的商品类的对象

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐