工厂三兄弟

Posted by Pismery Liu on Tuesday, October 30, 2018

TOC

工厂三兄弟

作用

一个类对象相关职责可以分为对象本身具有的职责、创建耦合对象职责、使用耦合对象职责;在工厂模式中强调,两个类A和B的关系要么A创建B要么A使用B;不应该两者都存在;

简单工厂模式(静态工厂模式)

意图

将类的创建对象职责剥离出来;

优缺点

优点:

  • 客户端不需要关心对象的创建过程,只需知道具体产品对应的参数。使得创建对象职责和使用对象职责分离;
  • 引入配置文件,可以在不修改客户端代码的前提下实现更换、添加具体产品类;但是工厂类添加时 需要修改代码

缺点:

  • 工厂集中了所有产品的创建逻辑,若工厂无法工作,整个系统将受到影响;
  • 工厂扩展难,违反开闭原则,若需要添加新产品需要修改工厂代码;
  • 工厂使用了静态工厂方法,使得工厂无法形成基于 继承的等级结构;

适用场景

  1. 工厂需要创建的产品比较少,不会造成工厂逻辑过于复杂;
  2. 客户端只需要知道参数,不关心创建过程;

结构图

代码

## 产品
public interface Car {
    void run();
}
public class BenzCar implements Car {
    @Override
    public void run() {
        log.debug("Benz is running");
    }
}
public class BMWCar implements Car {
    @Override
    public void run() {
        log.debug("BMW is running");
    }
}
public class MaseratiCar implements Car {
    @Override
    public void run() {
        log.debug("MaseratiCar is running");
    }
}

## 工厂
public class CarFactory {
    public static Car createCar(String carName) {
        Car result = null;
        switch (carName) {
            case "benz":
                result = new BenzCar();
                break;
            case "bmw":
                result = new BMWCar();
                break;
            case "maserati":
                result = new MaseratiCar();
                break;
            default:
                break;
        }
        return result;
    }
}

## 客户端
public class Client {
    public static void main(String[] args) {
        Car car = null;
        car =  CarFactory.createCar("benz");
        car.run();
        car = CarFactory.createCar("bmw");
        car.run();
        car = CarFactory.createCar("maserati");
        car.run();
        Config config = new Config();
        car = CarFactory.createCar(config.getCartype());
        car.run();
    }
}

// 运行结果
com.pismery.study.gof23.pattern.create.factory.simple.product.BenzCar - Benz is running
com.pismery.study.gof23.pattern.create.factory.simple.product.BMWCar - BMW is running
com.pismery.study.gof23.pattern.create.factory.simple.product.MaseratiCar - MaseratiCar is running

工厂方法模式

意图

改进简单工厂方法的工厂类扩展难,违反开闭原则和工厂集中过多的产品创建,若工厂无法工作,影响太大。

结构图

优缺点

优点:

  • 工厂类和产品类扩展时都能够符合开闭原则,在需要添加产品时,只需要添加一个产品类和工厂类;
  • 每一个工厂职责只负责一个产品的创建,减少事故的影响面积
  • 客户端只需要关心所需产品对应的工厂,无须关心创建细节,甚至无须知道具体产品类的类名。减少客户端记忆的开销;

缺点:

  • 类的复杂度高,每添加一个产品都需要相应添加一个工厂类

适用场景

  • 适用于简单工厂方法的场景但是产品类过多,或则产品创建过程过于复杂,用工厂方法;

扩展

  • 将产品类接口方法在工厂接口类中实现调用,能够完全通过工厂类实现所创建产品的功能,更加让客户端不需要知道产品类。但是这样工厂必须是抽象类不能是接口。
  • 重载创建方法提供多种创建方式;

代码

## 产品
public interface Car {
    void run();
}
public class BenzCar implements Car {
    @Override
    public void run() {
        log.debug("Benz is running");
    }
}
public class BMWCar implements Car {
    @Override
    public void run() {
        log.debug("BMW is running");
    }
}
public class MaseratiCar implements Car {
    @Override
    public void run() {
        log.debug("MaseratiCar is running");
    }
}

## 工厂
public abstract class CarFactory {
    public abstract Car createCar();

    public void run() {
        Car car = this.createCar();
        car.run();
    }
}
public class BenzFactory extends CarFactory {
    @Override
    public Car createCar() {
        return new BenzCar();
    }
}
public class BMWFatory extends CarFactory {
    @Override
    public Car createCar() {
        return new BMWCar();
    }
}
public class MaseratiFatory extends CarFactory{
    @Override
    public Car createCar() {
        return new MaseratiCar();
    }
}

## 客户端
@Slf4j
public class Client {
    public static void main(String[] args) {
        version1();
        version2();
    }
    private static void version1() {
        log.debug("version 1");
        CarFactory factory = new BenzFactory();
        Car car = factory.createCar();
        car.run();

        factory = new BMWFatory();
        car = factory.createCar();
        car.run();

        factory = new MaseratiFatory();
        car = factory.createCar();
        car.run();
    }
    private static void version2() {
        log.debug("version 2");
        new BenzFactory().run();
        new BMWFatory().run();
        new MaseratiFatory().run();
    }
}

// 运行结果
com.pismery.study.gof23.pattern.create.factory.nomal.Client - version 1
com.pismery.study.gof23.pattern.create.factory.nomal.product.BenzCar - Benz is running
com.pismery.study.gof23.pattern.create.factory.nomal.product.BMWCar - BMW is running
com.pismery.study.gof23.pattern.create.factory.nomal.product.MaseratiCar - MaseratiCar is running
com.pismery.study.gof23.pattern.create.factory.nomal.Client - version 2
com.pismery.study.gof23.pattern.create.factory.nomal.product.BenzCar - Benz is running
com.pismery.study.gof23.pattern.create.factory.nomal.product.BMWCar - BMW is running
com.pismery.study.gof23.pattern.create.factory.nomal.product.MaseratiCar - MaseratiCar is running

抽象工厂模式

引入概念

产品等级结构:指同一类产品的继承结构;例如电脑有戴尔电脑、小米电脑,外星人电脑;抽象的电脑和具体品牌电脑构成了一个产品等级结构;

产品族:在抽象工厂模式指同一个工厂所生产的位于不同的等级结构的一类产品;例如小米工厂生产小米电脑、小米手机、小米音箱,小米手环;

意图

当需求总是以一个产品族增加,若以工厂模式则需要为产品族下的所有产品添加一个具体工厂类导致工厂类数目暴增难以维护。因此抽象工厂模式以产品族为划分建立工厂,一个工厂能够创建一系列的不同产品等级结构的产品;

结构图

优缺点

优点:

  • 解决工厂模式中工厂类的暴增导致系统复杂度的提升;
  • 一个产品族中的多个不同产品等级对象设计成一起工作时,能够限制客户端只能操作同一产品族的对象;
  • 增加新的产品族很方便,符合开闭原则;

缺点:

  • 当要增加一个产品等级时,就需要更改工厂接口类和所有的具体工厂类,违反了开闭原则;
  • 需要设计人员设计时要考虑全面,设计完成后不会增加新的产品等级和删除已有产品等级;

适用场景

  • 当需求总是以一个产品族增加;
  • 需求不会增加新的产品等级和删除已有等级;

代码

ps: 因为代码过长,只列一个具体工厂,一类产品
## 产品
public interface Enginee {
    void start();
}
public interface Footbrake {
    void brake();
}
public interface Tyre {
    void rolling();
}

@Slf4j
public class SeniorEnginee implements Enginee {
    @Override
    public void start() {
        log.debug("SeniorEnginee start...");
    }
}
@Slf4j
public class SeniorFootbrake implements Footbrake {
    @Override
    public void brake() {
        log.debug("SeniorFootbrake braking...");
    }
}
@Slf4j
public class SeniorTyre implements Tyre {
    @Override
    public void rolling() {
        log.debug("SeniorTyre rolling");
    }
}

## 工厂
public interface AbstractFactory {
    Tyre createTyre();
    Enginee createEnginee();
    Footbrake createFootbrake();
}
public class SeniorFactory implements AbstractFactory {
    @Override
    public Tyre createTyre() {
        return new SeniorTyre();
    }

    @Override
    public Enginee createEnginee() {
        return new SeniorEnginee();
    }

    @Override
    public Footbrake createFootbrake() {
        return new SeniorFootbrake();
    }
}

## 客户端
@Slf4j
public class Client {
    public static void main(String[] args) {
        invoke(new MediuFactory());
    }

    private static void invoke(AbstractFactory normalFactory) {
        Tyre tyre = normalFactory.createTyre();
        Enginee enginee = normalFactory.createEnginee();
        Footbrake footbrake = normalFactory.createFootbrake();

        enginee.start();
        tyre.rolling();
        footbrake.brake();
    }
}

// 运行结果

com.pismery.study.gof23.pattern.create.factory.abstrct.Client - begin
com.pismery.study.gof23.pattern.create.factory.abstrct.product.mediu.MediuEnginee - MediuEnginee start...
com.pismery.study.gof23.pattern.create.factory.abstrct.product.mediu.MediuTyre - MediuTyre rolling
com.pismery.study.gof23.pattern.create.factory.abstrct.product.mediu.MediuFootbrake - MediuFootbrake braking...
com.pismery.study.gof23.pattern.create.factory.abstrct.Client - end