设计模式 —— 简单工厂模式、工厂模式和抽象工厂模式

本文探讨了为何在编程中使用工厂模式创建对象而非直接使用`new`关键字,强调了工厂模式在降低耦合性、方便扩展和修改方面的作用。简单工厂模式、工厂方法模式和抽象工厂模式被逐一介绍,包括它们的代码实现、优缺点。通过实例展示了如何创建键盘对象,说明了如何根据品牌创建不同类型的键盘,以及如何通过抽象工厂模式管理多个产品族的创建。工厂模式的应用有助于遵循开闭原则,实现系统的灵活扩展。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为何使用工厂模式创建对象而不是直接new

  1. 降低代码之间的耦合性
  2. 方便扩展和修改。举个例子:当前我创建了狗的对象,而且在代码中多处创建。那么需求修改了,我们需要将创建狗的对象都修改成猫。那么我们需要到程序中所有地方查找,修改。解决:创建一个动物的工厂,我们只需要配置一个字符串比如说狗,然后程序读取这个字符串从工厂中得到这个狗都对象。当我们修改的时候 ,我们只需要在工厂中添加一个猫的对象,然后修改配置的字符串为猫,这样工厂就会返回猫,其他所有用到读取配置然后创建对象的地方就直接拿到的是猫了。
  3. 客户端在调用时不想判断来实例化哪一个类或者实例化的过程过于复杂。在工厂模式中,具体的实现类创建过程对客户端是透明的客户端不需要管如何实现,客户端不决定具体实例化哪一个类,而是交由“工厂”来实例化。

简单工厂模式

定义

工厂模式提供了一种创建对象的最佳方式,我们在创建对象时不会对客户端暴露创建逻辑。简单来说就是定一个专门创建对象的工厂,我们把参数给他,然后他去产生相应对象。
在这里插入图片描述

代码实例

  1. 创建键盘接口,包含打印和输出方法。
  2. 创建不同键盘类继承接口,比如惠普和戴尔,他们实现各自的打印和输出功能
  3. 创建工厂类,提供一个方法,根据传入的字符串来决定创建哪个键盘对象并返回
  4. 使用:创建对象,然后传入参数,使用多态接收惠普键盘对象,调用方法。

public interface Keyboard {
    void print();
    void input(Context context);
}

class HPKeyboard implements Keyboard {

    @Override
    public void print() {
        //...输出逻辑;
    }

    @Override
    public void input(Context context) {
        //...输入逻辑;
    }

}

class DellKeyboard implements Keyboard {

    @Override
    public void print() {
        //...输出逻辑;
    }

    @Override
    public void input(Context context) {
        //...输入逻辑;
    }

}

class LenovoKeyboard implements Keyboard {

    @Override
    public void print() {
        //...输出逻辑;
    }

    @Override
    public void input(Context context) {
        //...输入逻辑;
    }

}

/**
 * 工厂
 */
public class KeyboardFactory {
    public Keyboard getInstance(int brand) {
        if(BrandEnum.HP.getCode() == brand){
            return new HPKeyboard();
        } else if(BrandEnum.LENOVO.getCode() == brand){
            return new LenovoKeyboard();
        } else if(BrandEnum.DELL.getCode() == brand){
            return new DellKeyboard();
        }
        return null;
    }
//测试
    public static void main(String[] args) {
        KeyboardFactory keyboardFactory = new KeyboardFactory();
        Keyboard lenovoKeyboard = KeyboardFactory.getInstance(BrandEnum.LENOVO.getCode());
        //...
    }

}

优点

  1. 一个调用者想创建一个对象,只要知道其名称就可以了。 创建简单。
  2. 屏蔽产品的具体实现

缺点

  1. 这种做法扩展性差,违背了开闭原则,也影响了可读性。每次增加一个类,就要在工厂中增加修改对象方法。可读性差。

工厂模式

定义

为了解决上面提到的"增加if-else"的问题,可以为每一个键盘子类建立一个对应的工厂子类。这样,创建不同品牌的键盘,只需要实现不同的工厂子类。当有新品牌加入时,新增具体工厂继承抽象工厂,而不用修改任何一个类。遵循开闭原则,扩展开放,修改关闭。

在这里插入图片描述

代码实例

  1. 创建一个键盘工厂
  2. 不同品牌键盘工厂创建自己的对象,就不需要一个公共的创建对象的工厂了。

public interface IKeyboardFactory {
    Keyboard getInstance();
}

public class HPKeyboardFactory implements IKeyboardFactory {
    @Override
    public Keyboard getInstance(){
        return new HPKeyboard();
    }
}

public class LenovoFactory implements IKeyboardFactory {
    @Override
    public Keyboard getInstance(){
        return new LenovoKeyboard();
    }
}

public class DellKeyboardFactory implements IKeyboardFactory {
    @Override
    public Keyboard getInstance(){
        return new DellKeyboard();
    }
}

优点

工厂模式同样体现了开闭原则,之后想要新增产品时,只需要扩展相应工厂类的实现即可。而不需要修改原用代码。

缺点

每一种品牌对应一个工厂子类,在创建具体键盘对象时,实例化不同的工厂子类。如果增加子品牌类的话,就要增加相应工厂。这样会使得系统中类的个数成倍增加,增加了代码的复杂度。

抽象工厂模式

他是工厂模式的大规模化
当我们有多个产品时,也就是有键盘,鼠标,显示器的时候。
抽象工厂是一个产品族的实现。工厂模式是在单一品牌产品下创建该产品工厂,而是抽象工厂模式,对每个品牌下面的产品族创建一个工厂,比如惠普品牌下有键盘,显示器,鼠标共同在一个工厂中创建对象。这样我们就可以通过某个品牌工厂创建一个产品族的所有产品。
在这里插入图片描述

代码实现

  1. 创建抽象键盘类以及各品牌键盘子类,实现打印功能
  2. 创建抽象鼠标类以及各品牌鼠标子类,实现移动功能。
  3. 创建抽象显示器类以及各品牌显示器,实现现实功能。
  4. 抽象工厂类:提供各种品牌创建的抽象,并提供抽象创建各种产品方法。
  5. 各品牌工厂类,继承抽象工厂类,提供各品牌内的各种产品的对象的创建(戴尔键盘,戴尔鼠标)。
  6. 客户端代码:创建戴尔工厂,然后我就可以根据需要创建戴尔工厂内各种产品的对象。
//产品1:各种键盘类
public interface Keyboard {
   void print();
}
public class DellKeyboard implements Keyboard {
    @Override
    public void print() {
        //...dell...dell;
    }
}
public class HPKeyboard implements Keyboard {
    @Override
    public void print() {
        //...HP...HP;
    }
}
//产品2:各种鼠标类
public interface Monitor {
   void play();
}
public class DellMonitor implements Monitor {
    @Override
    public void play() {
        //...dell...dell;
    }
}
public class HPMonitor implements Monitor {
    @Override
    public void play() {
        //...HP...HP;
    }
}
//产品3:各种显示器类
public interface MainFrame {
   void run();
}
public class DellMainFrame implements MainFrame {
    @Override
    public void run() {
        //...dell...dell;
    }
}
public class HPMainFrame implements MainFrame {
    @Override
    public void run() {
        //...HP...HP;
    }
}
//抽象工厂类:提供各种品牌创建的抽象
public interface IFactory {
    MainFrame createMainFrame();
    Monitor createMainFrame();
    Keyboard createKeyboard();
}
//各种工厂类:分为Dell工厂和HP工厂,各自负责品牌内产品的创建
public class DellFactory implements IFactory {
      @Override
      public MainFrame createMainFrame(){
                MainFrame mainFrame = new DellMainFrame();
             //...造一个Dell主机;
             return mainFrame;
      }

      @Override
      public Monitor createMonitor(){
                Monitor monitor = new DellMonitor();
             //...造一个Dell显示器;
             return monitor;
      }

      @Override
      public Keyboard createKeyboard(){
                Keyboard keyboard = new DellKeyboard();
             //...造一个Dell键盘;
             return Keyboard;
      }
}
public class HPFactory implements IFactory {
      @Override
      public MainFrame createMainFrame(){
                MainFrame mainFrame = new HPMainFrame();
             //...造一个HP主机;
             return mainFrame;
      }

      @Override
      public Monitor createMonitor(){
                Monitor monitor = new HPMonitor();
             //...造一个HP显示器;
             return monitor;
      }

      @Override
      public Keyboard createKeyboard(){
                Keyboard keyboard = new HPKeyboard();
             //...造一个HP键盘;
             return Keyboard;
      }
}

//客户端代码。实例化不同的工厂子类,可以通过不同的创建方法创建不同的产品
public class Main {
    public static void main(String[] args) {
        IFactory dellFactory = new DellFactory();
        IFactory HPFactory = new HPFactory();
        //创建戴尔键盘
        Keyboard dellKeyboard = dellFactory.createKeyboard();
        //...
    }
}

优点

  1. 增加产品族很简单,比如再增加一个联想产品族,我们创建工厂和对应产品类。

缺点

扩展产品较复杂,比如我新增一个打印机产品,那么每个品牌都需要增加打印机产品类,每个工厂中也要增加产品实现。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Charles Ray

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值