掘金 后端 ( ) • 2024-03-27 13:34

工厂模式

简单工厂模式

简单工厂模式将被使用方的创建过程封装到一个类中,这样就在使用方和被使用方之间做了一个缓冲,也就是将被使用方和被使用方进行解耦(降低了使用方和被使用方的耦合度),提高了软件的可扩展性、可维护性和可复用性。

案例:

UML类图:

简单工厂模式.jpg

消费者Consumer类:

/**
 * 购买牙膏的消费者
 */
public class Consumer {

    public static void main(String[] args) {
        Shop shop = new Shop();
        Toothpaste boughtToothpaste1 = shop.sellToothpaste("中华牌");
        System.out.println("消费者买到了" + boughtToothpaste1);
        System.out.println("================");
        Toothpaste boughtToothpaste2 = shop.sellToothpaste("高露洁牌");
        System.out.println("消费者买到了" + boughtToothpaste2);
    }
}

商店Shop类:

/**
 * 商店类用于用户消费者购买牙膏
 */
public class Shop {

    /**
     * 卖牙膏方法
     *
     * @param brand 牙膏品牌
     * @return 牙膏对象
     */
    public Toothpaste sellToothpaste(String brand) {
        return SimpleFactory.createToothpaste(brand);
    }
}

简单工厂SimpleFactory类:

/**
 * 用于生产牙膏的简单工厂
 */
public class SimpleFactory {

    /**
     * 创建牙膏方法
     */
    public static Toothpaste createToothpaste(String brand) {
        Toothpaste toothpaste = null;
        if ("中华牌".equals(brand)) {
            toothpaste = new ZhongHuaToothpaste();
        } else if ("高露洁牌".equals(brand)) {
            toothpaste = new GaoLuJieToothpaste();
        }
        if (toothpaste != null) {
            toothpaste.createPaste();
            toothpaste.createShell();
            toothpaste.pack();
        }
        return toothpaste;
    }
}

牙膏抽象Toothpaste类:

/**
 * 牙膏抽象类
 */
public abstract class Toothpaste {

    protected String brand;

    public void createPaste() {
        System.out.println("产生了" + brand + "的膏体");
    }

    public void createShell() {
        System.out.println("产生了" + brand + "的外壳");
    }

    public abstract void pack();

    @Override
    public String toString() {
        return brand + "的牙膏";
    }
}

高露洁牙膏GaoLuJieToothpaste实现类:

/**
 * 高露洁牌牙膏
 */
public class GaoLuJieToothpaste extends Toothpaste {

    public GaoLuJieToothpaste() {
        this.brand = "高露洁牌";
    }

    @Override
    public void pack() {
        System.out.println("给" + brand + "牙膏进行了包装!");
    }
}

中华牙膏ZhongHuaToothpaste实现类:

/**
 * 中华牌牙膏
 */
public class ZhongHuaToothpaste extends Toothpaste {

    public ZhongHuaToothpaste() {
        this.brand = "中华牌";
    }

    @Override
    public void pack() {
        System.out.println("给" + brand + "牙膏进行了包装!");
    }
}

总结:

  • 简单工厂将使用方和被使用方进行解耦,提高了软件的可扩展性、可维护性和可复用性。

  • 但是还是违背了开闭原则(OCP原则),如果后续要扩展新的功能,需要修改简单工厂的工厂类对象中创建对象的代码。

  • 使用场景:简单工厂模式适用于具体类十分确定且固定的一类产品的创建,这样才能不太频繁的修改简单工程类去实现扩展。

工厂方法模式

将简单工厂中得到对象的方法写成一个抽象方法,也就是说在工厂类或者接口中不知道如何创建该对象,具体如何创建交给子类或者实现类去决定

案例:

UML类图:

工厂方法模式.jpg

消费者Consumer类:

/**
 * 购买牙膏的消费者
 */
public class Consumer {

    public static void main(String[] args) {
        Shop shop = new Shop();
        Toothpaste boughtToothpaste1 = shop.sellToothpaste(new ZhongHuaFactory());
        System.out.println("消费者买到了" + boughtToothpaste1);
        System.out.println("================");
        Toothpaste boughtToothpaste2 = shop.sellToothpaste(new GaoLuJieFactory());
        System.out.println("消费者买到了" + boughtToothpaste2);
    }
}

商店Shop类:

/**
 * 商店类用于用户消费者购买牙膏
 */
public class Shop {

    /**
     * 卖牙膏方法
     * @param toothpasteFactory  牙膏品牌工厂
     * @return  牙膏对象
     */
    public Toothpaste sellToothpaste(ToothpasteFactory toothpasteFactory) {

        return toothpasteFactory.createToothpaste();
    }
}

牙膏工厂ToothpasteFactory接口类:

/**
 * 用于生产牙膏的工厂
 * 将简单工厂模式中的工厂类换成一个抽象类或者接口
 * 并提供一个用户创建对象的抽象方法,也就是将创建对象
 * 的过程下沉到实现类或者子类去实现。
 */
public interface ToothpasteFactory {

    /**
     * 创建牙膏方法(这个方法就是工厂方法)
     * @return
     */
    Toothpaste createToothpaste();
}

中华牙膏工厂ZhongHuaFactory类:

/**
 * 中华牌工厂类
 */
public class ZhongHuaFactory implements ToothpasteFactory {

    @Override
    public Toothpaste createToothpaste() {
        Toothpaste toothpaste = new ZhongHuaToothpaste();
        toothpaste.createPaste();
        toothpaste.createShell();
        toothpaste.pack();
        return toothpaste;
    }
}

高露洁牙膏工厂GaoLuJieFactory类:

/**
 * 高露洁牌工厂类
 */
public class GaoLuJieFactory implements ToothpasteFactory{

    @Override
    public Toothpaste createToothpaste() {
        Toothpaste toothpaste = new GaoLuJieToothpaste();
        toothpaste.createPaste();
        toothpaste.createShell();
        toothpaste.pack();
        return toothpaste;
    }
}

牙膏Toothpaste抽象类:

/**
 * 牙膏抽象类
 */
public abstract class Toothpaste {

    protected String brand;

    public void createPaste() {
        System.out.println("产生了" + brand + "的膏体");
    }

    public void createShell() {
        System.out.println("产生了" + brand + "的外壳");
    }

    public abstract void pack();

    @Override
    public String toString() {
        return brand + "的牙膏";
    }
}

高露洁牙膏GaoLuJieToothpaste类:

/**
 * 高露洁牌牙膏
 */
public class GaoLuJieToothpaste extends Toothpaste {

    public GaoLuJieToothpaste() {
        this.brand = "高露洁牌";
    }

    @Override
    public void pack() {
        System.out.println("给" + brand + "牙膏进行了包装!");
    }
}

中华牙膏ZhongHuaToothpaste类:

/**
 * 中华牌牙膏
 */
public class ZhongHuaToothpaste extends Toothpaste {

    public ZhongHuaToothpaste() {
        this.brand = "中华牌";
    }

    @Override
    public void pack() {
        System.out.println("给" + brand + "牙膏进行了包装!");
    }
}

总结:

  • 将简单工厂中得到对象的方法写成一个抽象方法,其具体的类提供不同的工厂类来继承,实现类各自实现自己的工厂父类,这样遵循了开闭原则,我们只需要对其进行扩展,不需要修改任何原有类代码。

  • 但这种方式会随着子工厂类和其实现类的增多而增加类的复杂度。

  • 推荐使用这种方式。

抽象工厂模式

提供一个创建一系列相关或者相互依赖的对象的工厂接口,而无需指定它们具体的类。其作用是产生一个产品系列或者是产品簇。

UML类图:

抽象工厂模式.jpg

消费者Consumer类:
/**
 * 购买刷牙工具的消费者
 */
public class Consumer {

    public static void main(String[] args) {
        Shop shop = new Shop();
        String boughtToothbrushingUtil = shop.sellToothbrushUtils(new ZhongHuaFactory());
        System.out.println("消费者买到了" + boughtToothbrushingUtil);
        System.out.println("================");
        String boughtToothbrushingUtil2 = shop.sellToothbrushUtils(new GaoLuJieFactory());
        System.out.println("消费者买到了" + boughtToothbrushingUtil2);
    }
}

商店Shop类:

/**
 * 商店类用于用户消费者购买刷牙工具
 */
public class Shop {

    /**
     * 卖刷牙工具方法
     *
     * @param toothBrushingFactory 刷牙工具的品牌工厂
     * @return 刷牙工具对象
     */
    public String sellToothbrushUtils(ToothBrushingFactory toothBrushingFactory) {
        Toothpaste toothpaste = toothBrushingFactory.createToothpaste();
        Toothbrush toothbrush = toothBrushingFactory.createToothbrush();

        return toothpaste + "和" + toothbrush;
    }
}

工厂接口ToothBrushingFactory:

/**
 * 用于生产刷牙工具的工厂
 * 工厂方法模式产生的产品都是一个类或接口的子类实例,
 * 抽象工厂模式产生的产品是多个接口或抽象类的子类实例。
 */
public interface ToothBrushingFactory {

    /**
     * 创建牙膏方法
     *
     * @return
     */
    Toothpaste createToothpaste();

    /**
     * 创建牙刷方法
     *
     * @return
     */
    Toothbrush createToothbrush();
}

中华牌工厂ZhongHuaFactory类:

/**
* 中华牌工厂类
*/
public class ZhongHuaFactory implements ToothBrushingFactory {

   @Override
   public Toothpaste createToothpaste() {
       Toothpaste toothpaste = new ZhongHuaToothpaste();
       toothpaste.createPaste();
       toothpaste.createShell();
       toothpaste.pack();
       return toothpaste;
   }

   @Override
   public Toothbrush createToothbrush() {
       Toothbrush toothbrush = new ZhongHuaToothbrush();
       toothbrush.createHandle();
       toothbrush.createHair();
       toothbrush.pack();
       return toothbrush;
   }
}

高露洁牌工厂类

/**
 * 高露洁工厂类
 */
public class GaoLuJieFactory implements ToothBrushingFactory {

    @Override
    public Toothpaste createToothpaste() {
        Toothpaste toothpaste = new GaoLuJieToothpaste();
        toothpaste.createPaste();
        toothpaste.createShell();
        toothpaste.pack();
        return toothpaste;
    }

    @Override
    public Toothbrush createToothbrush() {
        Toothbrush toothbrush = new GaoLuJieToothbrush();
        toothbrush.createHandle();
        toothbrush.createHair();
        toothbrush.pack();
        return toothbrush;
    }
}

牙刷Toothbrush抽象类:

/**
 * 牙刷抽象类
 */
public abstract class Toothbrush {

    protected String brand;

    public void createHair() {
        System.out.println("产生了" + brand + "的牙刷毛");
    }

    public void createHandle() {
        System.out.println("产生了" + brand + "的手柄");
    }

    public abstract void pack();

    @Override
    public String toString() {
        return brand + "的牙刷";
    }
}

中华牌牙刷ZhongHuaToothbrush类:

/**
 * 中华牌牙刷
 */
public class ZhongHuaToothbrush extends Toothbrush {

    public ZhongHuaToothbrush() {
        this.brand = "中华牌";
    }

    @Override
    public void pack() {
        System.out.println("给" + brand + "牙刷进行了组装!");
    }
}

高露洁牌牙刷GaoLuJieToothbrush类:

/**
 * 高露洁牌牙刷
 */
public class GaoLuJieToothbrush extends Toothbrush {

    public GaoLuJieToothbrush() {
        this.brand = "高露洁牌";
    }

    @Override
    public void pack() {
        System.out.println("给" + brand + "牙刷进行了组装!");
    }
}

牙膏Toothpaste抽象类:

/**
 * 牙膏抽象类
 */
public abstract class Toothpaste {

    protected String brand;

    public void createPaste() {
        System.out.println("产生了" + brand + "的膏体");
    }

    public void createShell() {
        System.out.println("产生了" + brand + "的外壳");
    }

    public abstract void pack();

    @Override
    public String toString() {
        return brand + "的牙膏";
    }
}

中华牌牙膏ZhongHuaToothpaste类:

/**
 * 中华牌牙膏
 */
public class ZhongHuaToothpaste extends Toothpaste {

    public ZhongHuaToothpaste() {
        this.brand = "中华牌";
    }

    @Override
    public void pack() {
        System.out.println("给" + brand + "牙膏进行了包装!");
    }
}

高露洁牌牙膏GaoLuJieToothpaste类:

/**
 * 高露洁牌牙膏
 */
public class GaoLuJieToothpaste extends Toothpaste {

    public GaoLuJieToothpaste() {
        this.brand = "高露洁牌";
    }

    @Override
    public void pack() {
        System.out.println("给" + brand + "牙膏进行了包装!");
    }
}

总结:

  • 工厂方法模式产生的产品都是一个类或接口的子类实例,抽象工厂模式产生的产品是多个接口或抽象类的子类实例。

  • 这种方式其实也可以单独的把它看做一个设计模式(包含在23种设计模式之中)。

  • 当关心的是一个产品簇对象的创建时,推荐使用此方式。