设计模式之工厂模式

Posted on 2021-11-10 21:51  梁小迪  阅读(95)  评论(0)    收藏  举报

1、解决的问题

将原来分散在各个地方的对象创建过程单独抽离出来,交给工厂类进行创建。

其他的地方想要创建对象直接找工厂(调用对象的方法)进行创建。

2、工厂模式的三种类型

  1、简单工厂

  2、工厂方法

  3、抽象工厂

3、简单工厂(不属于23种设计模式)

定义:一个工厂类根据传入不同的参数返回不同的实例,所有的实例都有共同的父类或者接口。

适用场景:

  • 由于只有一个工厂类,所以必须保证工厂类里面创建对象的逻辑不能过于复杂
  • 工厂类对外屏蔽了创建对象的过程,客户端获取对象的创建是无感知的

拿泡茶为例,茶叶有好多种类,比如龙井、碧螺春、毛尖等。
首先一个ITea接口:

1 public interface ITea {
2     // 沏茶
3     public void makeTea();
4 }

再定义两种类型的茶,西湖龙井和碧螺春:

public class LongjingTea implements ITea {
    @Override
    public void makeTea() {
        System.out.println("西湖龙井");
    }
}

public class BiluochunTea implements ITea{
    @Override
    public void makeTea() {
        System.out.println("碧螺春");
    }
}

假如其它有一处代码要使用“茶”这个对象沏一壶茶,有如下代码:

 1     /**
 2      *  准备沏一杯茶,根据传入的参数决定不同的茶叶类型
 3      */
 4     public ITea prepareTea(String type){
 5         ITea tea = null;
 6         if(type.equals("longjing")){
 7             tea = new LongjingTea();
 8         }else if(type.equals("biluochun")){
 9             tea = new BiluochunTea();
10         }
11         if(tea != null){
12             tea.makeTea();
13         }
14         return tea;
15     }

接下来,我们可以分析下不使用工厂模式的情况:

如果我们的工程中不是一处用了类似这段代码逻辑,那增加一种茶叶的类型(比如毛尖)就需要修改多处代码,不利于维护。

因此,可以考虑,将创建茶叶对象的逻辑抽离出来,单独放到一个类中,这个类便是工厂类(专门生产茶叶的工厂)。这样维护起来便方便很多,客户端代码也无需知道对象创建的具体细节,只需要从工厂类中获取对象即可。

简单工厂类实现如下:

 1 public class TeaFactory {
 2 
 3     public ITea createTea(String type){
 4         ITea tea = null;
 5         if(type.equals("longjing")){
 6             tea = new LongjingTea();
 7         }else if(type.equals("biluochun")){
 8             tea = new BiluochunTea();
 9         }
10         if(tea != null){
11             tea.makeTea();
12         }
13         return tea;
14     }
15 }

客户端代码要使用茶对象,需要从工厂中获取:

1     public static void main(String[] args) {
2 
3         TeaFactory teaFactory = new TeaFactory();
4         ITea tea = teaFactory.createTea("longjing");
5     }

 

 

 

二、工厂方法模式

在上面的简单工厂中,如果要创建的产品类型较多,且各个产品创建的过程不尽相同,则一个工厂类职责会变得越来越多,不符合单一职责原则。另外简单工厂也不符合开闭原则。要新增一种产品需要修改原来的工厂类。因此,工厂方法模式中,将生产各种类型的产品的工厂也做了抽象分离。比如,上面例子中的,生产龙井的有专门的龙井工厂,生产碧螺春的有专门的碧螺春工厂。

工厂方法模式中,针对不同的对象提供不同的工厂,每个对象都有一个与之对应的工厂,koi是定义一个用于创建对象的接口,让子类决定初始化哪一个类,将实例化延迟到其子类。

定义:定义一个用于创建对象的接口,让子类决定将哪一个类实例化

适用场景:

  • 客户端不需要知道它所创建的对象的类。只知道创建它的工厂名就完成了创建过程。
  • 客户端可以通过子类来指定创建对应的对象。

首先创建统一的工厂接口:

1 /**
2  * 生产茶叶的统一接口
3  */
4 public interface ITeaFactory {
5 
6     // 生产茶叶
7     public ITea createTea();
8 }

然后创建两个生产不同类型产品的工厂实现类:

public class LongjingTeaFactory implements ITeaFactory{
    @Override
    public ITea createTea() {
        return new LongjingTea();
    }
}

public class BiluochunTeaFactory implements ITeaFactory{
    @Override
    public ITea createTea() {
        return new BiluochunTea();
    }
}

客户端代码:

public class FactoryMethodTest {
    public static void main(String[] args) {
        ITeaFactory factory = new LongjingTeaFactory();
        factory.createTea();

        factory = new BiluochunTeaFactory();
        factory.createTea();
    }
}

如果要新增一种茶叶,比如毛尖,只需要新建一个生产毛尖的工厂类实现ITeaFactory即可。

可以看到符合开闭原则、单一职责原则。

 

 

 

 

 

工厂方法适用于以下场景:
1、创建对象需要大量重复的代码。
2、客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
3、一个类通过其子类来指定创建哪个对象。

工厂方法也有缺点:
1、类的个数容易过多,增加复杂度。
2、增加了系统的抽象性和理解难度。

三、抽象工厂

举例说明下,有两个工厂,美的、格力。这两个工厂都生产两种产品:冰箱和洗衣机。

下面使用抽象工厂模式来描述每个工厂的两种产品的创建过程。

1、首先创建两个产品的接口类:

 1 /**
 2  * 冰箱
 3  */
 4 public interface IFridge {
 6     // 冷藏
 7     void coldStorage();
 8 }
 9 
10 /**
11  * 洗衣机
12  */
13 public interface IWasher {
14     void wash();
15 }

2、创建每个工厂的两种产品(总共四种产品):

美的的冰箱和洗衣机:

 1 public class MeideFridge implements IFridge{
 2     @Override
 3     public void coldStorage() {
 4         System.out.println("美的冰箱");
 5     }
 6 }
 7 
 8 public class MeideWasher implements IWasher {
 9     @Override
10     public void wash() {
11         System.out.println("美的洗衣机");
12     }
13 }

格力的冰箱和洗衣机:

 1 public class GeliFridge implements IFridge {
 2     @Override
 3     public void coldStorage() {
 4         System.out.println("格力冰箱");
 5     }
 6 }
 7 
 8 public class GeliWasher implements IWasher{
 9     @Override
10     public void wash() {
11         System.out.println("格力洗衣机");
12     }
13 }

3、创建抽象工厂接口

家用电器工厂,生产一组产品。

1 /**
2  * 抽象工厂接口,家用电器工厂,生产冰箱和洗衣机
3  */
4 public interface IHouseholdElectricFactory {
5 
6     IFridge createFridge();
7 
8     IWasher createWasher();
9 }

4、创建具体产品等级的工厂

这里是创建美的和格力的工厂实现类。

 1 public class MeideHouseholdFactory implements IHouseholdElectricFactory{
 2     @Override
 3     public IFridge createFridge() {
 4         return new MeideFridge();
 5     }
 6 
 7     @Override
 8     public IWasher createWasher() {
 9         return new MeideWasher();
10     }
11 }
12 
13 public class GeliHouseholdFactory implements IHouseholdElectricFactory{
14     @Override
15     public IFridge createFridge() {
16         return new GeliFridge();
17     }
18 
19     @Override
20     public IWasher createWasher() {
21         return new GeliWasher();
22     }
23 }

5、客户端代码使用

1 public class AbsFactoryTest {
2     public static void main(String[] args) {
3 
4         IHouseholdElectricFactory factory = new MeideHouseholdFactory();
5         factory.createFridge().coldStorage();
6         factory.createWasher().wash();
7     }
8 }

 

工厂模式浅析

 

@

工厂模式主要分为简单工厂模式、工厂方法模式、抽象工厂模式,我们常说的工厂模式指的就是工厂方法模式。其中简单工厂模式不属于23种设计模式。

简单工厂模式

简单工厂模式并不属于23种设计模式,只是属于一种习惯,一种写代码的习惯

定义

一个工厂类根据传入不同的参数返回不同的实例,所有的实例都有共同的父类或者接口。

使用场景

  • 由于只有一个工厂类,所以必须保证工厂类里面创建对象的逻辑不能过于复杂
  • 工厂类对外屏蔽了创建对象的过程,客户端获取对象的创建是无感知的

实例

一个可以绘制圆形、正方形、长方形的绘图器
1、定义通用接口

-w337

2、创建圆形、正方形、长方形具体的实例对象
-w456
-w441
-w481

3、创建工厂实现类
-w660

4、获取对象
-w537
通过传入不同的参数获取对象创建图形

工厂方法模式

工厂方法模式中,针对不同的对象提供不同的工厂,每个对象都有一个与之对应的工厂,koi是定义一个用于创建对象的接口,让子类决定初始化哪一个类,将实例化延迟到其子类。

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3