我与GPT老师的对话---设计模式之工厂模式

我:
你现在扮演一个软件高级工程师的角色,为我讲解接下来的问题。

GPT老师:
好的,请问需要我讲解什么问题?

我:
讲一讲工厂模式。

GPT老师:
工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们不会对客户端暴露创建对象的具体逻辑,而是通过使用一个共同的接口来指向新创建的对象。这样做的好处在于,如果想要改变一个类的实例化方式,只需要修改工厂类即可,而不需要修改客户端代码。

具体的实现方式有多种,其中比较常用的包括简单工厂模式、工厂方法模式和抽象工厂模式等。简单工厂模式是将所有的实例化逻辑都放在一个工厂类中实现,而工厂方法模式则是将不同类的实例化逻辑分别放在不同的工厂子类中实现。抽象工厂模式进一步将工厂接口抽象化,同时将一组相关的产品组合成一个工厂类。

工厂模式的优点在于可以隐藏实例化对象的复杂度,客户端只需要知道所需的产品名即可获取对应的实例对象,从而简化了客户端代码,并且增加了代码的可维护性和扩展性。同时,工厂模式还可以与其他设计模式结合使用,如单例模式、策略模式等,进一步优化设计。

我:
利用java代码举例说明简单工厂模式

GPT老师:
好的,下面是一个使用 Java 代码实现简单工厂模式的示例。
我们首先定义一个 Animal 接口,它包含一个 void sound() 方法:

public interface Animal {
    void sound();
}

然后我们创建两个具体的实现类 Dog 和 Cat,它们都实现了 Animal 接口:

public class Dog implements Animal {
    @Override
    public void sound() {
        System.out.println("汪汪汪");
    }
}

public class Cat implements Animal {
    @Override
    public void sound() {
        System.out.println("喵喵喵");
    }
}

接着我们创建一个简单工厂类 AnimalFactory,它包含一个 createAnimal(String type) 方法,根据传入的参数返回对应的 Animal 实现类的实例:

public class AnimalFactory {
    public static Animal createAnimal(String type) {
        Animal animal = null;
        if ("dog".equalsIgnoreCase(type)) {
            animal = new Dog();
        } else if ("cat".equalsIgnoreCase(type)) {
            animal = new Cat();
        }
        return animal;
    }
}

最后我们可以在客户端代码中调用工厂方法来创建具体的实例对象:

public class Client {
    public static void main(String[] args) {
        Animal dog = AnimalFactory.createAnimal("dog");
        dog.sound(); //输出:汪汪汪

        Animal cat = AnimalFactory.createAnimal("cat");
        cat.sound(); //输出:喵喵喵
    }
}

这里给出UML类图:
简单工厂模式
在上面的代码中,我们可以看到客户端代码只需要调用 AnimalFactory.createAnimal() 方法,而不需要关心具体的实例化过程。如果我们想要增加另一种动物的实现类,只需要新增一个实现了 Animal 接口的类即可,无需修改客户端代码和工厂类的代码,从而增加了代码的可维护性和扩展性。

注意,在简单工厂模式中,工厂类通常采用静态方法来实现,从而避免每次都创建新的工厂对象。

我:
利用java代码举例说明工厂方法模式

GPT老师:
好的,下面是一个使用 Java 代码实现工厂方法模式的示例。我们首先定义一个 Animal 接口,它包含一个 void sound() 方法:

public interface Animal {
    void sound();
}

然后我们创建两个具体的实现类 Dog 和 Cat,它们都实现了 Animal 接口:

public class Dog implements Animal {
    @Override
    public void sound() {
        System.out.println("汪汪汪");
    }
}

public class Cat implements Animal {
    @Override
    public void sound() {
        System.out.println("喵喵喵");
    }
}

接着我们创建一个抽象工厂类 AnimalFactory,它包含一个抽象的 createAnimal() 方法,该方法被具体工厂类实现来创建具体的 Animal 实现类的实例:

public abstract class AnimalFactory {
    public abstract Animal createAnimal();
}

然后我们创建两个具体的工厂类 DogFactory 和 CatFactory,它们都继承自 AnimalFactory 并实现了 createAnimal() 方法,分别用于创建 Dog 和 Cat 的实例:

public class DogFactory extends AnimalFactory{
    @Override
    public Animal createAnimal() {
        return new Dog();
    }
}

public class CatFactory extends AnimalFactory{
    @Override
    public Animal createAnimal() {
        return new Cat();
    }
}

最后我们可以在客户端代码中调用具体的工厂类的 createAnimal() 方法来创建具体的实例对象:

public class Client {
    public static void main(String[] args) {
        AnimalFactory dogFactory = new DogFactory();
        Animal dog = dogFactory.createAnimal();
        dog.sound(); //输出:汪汪汪

        AnimalFactory catFactory = new CatFactory();
        Animal cat = catFactory.createAnimal();
        cat.sound(); //输出:喵喵喵
    }
}

这里给出UML类图:
工厂方法模式
在上面的代码中,我们可以看到客户端代码不需要直接调用具体的实现类的构造函数,而是通过对应的工厂类来创建实例。这样客户端只需要知道需要什么类型的对象即可,无需关心对象的具体创建过程,从而更加符合面向对象设计原则。

注意,在工厂方法模式中,抽象工厂类通常不包含具体的产品实现类,它只定义用于创建产品的抽象方法。具体的产品创建由其子类(即具体工厂类)完成。

我:
利用java代码举例说明抽象工厂模式。

GPT老师:
好的,下面是一个使用 Java 代码实现抽象工厂模式的示例。我们首先定义两个接口 Phone 和 Computer,它们分别表示手机和电脑,每个接口都包含一个 void info() 方法,用于输出产品信息:

public interface Phone {
    void info();
}

public interface Computer {
    void info();
}

然后我们创建两个具体的实现类 MiPhone 和 MiComputer,它们分别实现了 Phone 和 Computer 接口:

 public class MiPhone implements Phone {
    @Override
    public void info() {
        System.out.println("小米手机");
    }
}

public class MiComputer implements Computer {
    @Override
    public void info() {
        System.out.println("小米电脑");
    }
}

接着我们创建一个抽象工厂类 AbstractFactory,它包含两个抽象的方法 createPhone() 和 createComputer(),该方法被具体工厂类实现来创建具体的 Phone 和 Computer 实现类的实例:

public abstract class AbstractFactory {
    public abstract Phone createPhone();
    public abstract Computer createComputer();
}

然后我们创建两个具体的工厂类 MiFactory 和 HuaweiFactory,它们都继承自 AbstractFactory 并实现了 createPhone() 和 createComputer() 方法,分别用于创建小米品牌和华为品牌的手机和电脑:

public class MiFactory extends AbstractFactory {
    @Override
    public Phone createPhone() {
        return new MiPhone();
    }

    @Override
    public Computer createComputer() {
        return new MiComputer();
    }
}

public class HuaweiFactory extends AbstractFactory {
    @Override
    public Phone createPhone() {
        return new HuaweiPhone();
    }

    @Override
    public Computer createComputer() {
        return new HuaweiComputer();
    }
}

最后我们可以在客户端代码中调用具体的工厂类的 createPhone() 和 createComputer() 方法来创建具体的实例对象:

public class Client {
    public static void main(String[] args) {
        AbstractFactory miFactory = new MiFactory();
        Phone miPhone = miFactory.createPhone();
        miPhone.info(); //输出:小米手机
        Computer miComputer = miFactory.createComputer();
        miComputer.info(); //输出:小米电脑

        AbstractFactory huaweiFactory = new HuaweiFactory();
        Phone huaweiPhone = huaweiFactory.createPhone();
        huaweiPhone.info(); //输出:华为手机
        Computer huaweiComputer = huaweiFactory.createComputer();
        huaweiComputer.info(); //输出:华为电脑
    }
}

这里给出UML类图:
抽象工厂模式
在上面的代码中,我们可以看到客户端代码只需要知道需要什么品牌的手机和电脑即可,无需关心具体产品的实现过程。这样可以使得客户端与具体实现解耦,并且方便地进行产品族的扩展。

注意,在抽象工厂模式中,抽象工厂用于创建一族相关或者相互依赖的对象,所以每个工厂类都可以创建多个产品对象。这与工厂方法模式在一个工厂中只创建一个对象不同。

我:
利用java举例说明简单工厂模式、工厂方法模式和抽象工厂模式的优缺点

GPT老师:
一、简单工厂模式

简单工厂模式(Simple Factory Pattern)属于创建型模式,是通过一个工厂类根据传入的参数,动态决定应该创建哪一个具体产品类的实例。

优点:简单易懂,容易实现。由于在客户端代码中只需要通过工厂类创建产品对象,无需关心具体产品对象的创建过程,从而将客户端代码与具体产品对象解耦,使得客户端代码更加灵活。

缺点:工厂类承担了过多的职责,一旦这个工厂出现问题,就会影响整个系统。每次新增一个产品都需要修改工厂类的源代码,不符合开闭原则。当产品类型较多时,会导致工厂类代码过于庞大。

二、工厂方法模式

工厂方法模式(Factory Method Pattern)是指定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

优点:相对于简单工厂模式,它更符合开闭原则,因为每增加一个产品类,就需要增加一个对应的工厂类,而不需要修改已有工厂类的代码。由于不再需要由一个工厂类承担创建所有产品类的职责,每个具体工厂类只需要负责创建对应的产品即可,从而使得每个具体工厂类的代码量都大幅减少。
更容易扩展产品族。

缺点:当新增一个产品等级结构时,需要新增对应的抽象产品类和具体产品类,同时也需要新增对应的抽象工厂类和具体工厂类,这样会导致代码的数量增加。在 Java 中最常见的使用工厂方法模式的场景是日志框架的实现,例如 Apache Commons Logging。

三、抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)提供一个用于创建一系列相关或相互依赖对象的接口,无需指定具体的类。

优点:可以保证客户端始终只使用同一产品族中的对象。从而避免了产品可能出现的不兼容问题。抽象工厂模式可以针对不同的产品等级结构(即不同的产品类型)设计不同的实现类,从而提高了系统的灵活性。扩展性好,能够方便地支持新的产品族的扩展。

缺点:当新增一个产品等级结构时,需要新增对应的抽象产品类和具体产品类,同时也需要新增对应的抽象工厂类和具体工厂类,这样会导致代码的数量增加。

猜你喜欢

转载自blog.csdn.net/m0_37742400/article/details/130075580