设计模式之工厂模式(简单工厂,工厂方法,抽象工厂)

前语:在工厂模式中常常会分不清楚(简单工厂和工厂方法,抽象工厂)三者之前的区别,在学习设计模式时也容易混淆,这里对三者进行学习;

工厂模式:顾名思义,客户希望通过工厂(一个或一系列方法)去生产(一个或者一系列产品的实例)

本质:工厂模式是创建者模式,创建对象实例;

一.简单工厂

  简单工厂类(SimpleFactory)通过接受参数的形式,调用getShape()方法区得到想要创建的对象;

      如图所示:

 优点:简单而且粗暴的创建对象,通过参数可以创建任何实现了接口的对象

 缺点:(1)当对象类过多,简单工厂就会很臃肿,不利于简单工厂的维护 (2)不符合开放封闭原则,每次增加一个产品子类,就需要修改简单工厂

 简单写了一下实现代码:但是不是按照上述UML关系图

产品接口Food的代码如下

1
2
3
public interface Food {
    void eat();
}

实现产品接口的类Apple.class

1
2
3
4
5
6
public class Apple implements   Food {
    @Override
    public void eat() {
        System.out.println("当前吃是苹果");
    }
}

实现产品接口的类Pear.class

1
2
3
4
5
6
public class Pear implements Food {
    @Override
    public void eat() {
        System.out.println("当前正在吃梨子");
    }
}

实现产品接口的类Banana.class

1
2
3
4
5
6
public class Banana implements Food{
    @Override
    public void eat() {
        System.out.println("当前正在吃香蕉");
    }
}

简单工厂方法SimpleFactory.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class SimpleFactory {
 
    private Food food=null;
 
    public Food getFood(String FoodName){
        if(FoodName=="" || FoodName==null){
            return null;
        }
 
        switch (FoodName){
            case "Banana": food =new Banana();break;
            case "Apple" : food =new Apple(); break;
            case "Pear"  : food =new Pear();break;
            default: food=null;break;
        }
        return food;
    }
}

方法运行Main

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//简单工厂
//1.对象类型 有多种子类
//2.工厂只有 一个
//3.对象的创建延迟到工厂实例中
public class Main {
 
    public static void main(String[] args) {
        //Client 客户来吃水果
        Food food =null;
 
        SimpleFactory factory =new SimpleFactory();
 
        food=factory.getFood("Pear");
 
        food.eat();
    }
}

运行结果:

 二.工厂方法

工厂方法为每一个对象提供一种产品提供一个工厂,用于该类的实例化;

如下UML所示为工厂方法。

 

 

工厂方法的实现过程代码:

Food接口

1
2
3
public interface  Food {
     void eat();
}

Factory接口

1
2
3
public interface Factory {
    Food create();
}

Apple.class类

1
2
3
4
5
6
public class Apple implements   Food {
    @Override
    public void eat() {
        System.out.println("当前吃是苹果");
    }
}

Banana.class类

1
2
3
4
5
6
7
public class Banana implements Food{
 
    @Override
    public void eat() {
        System.out.println("当前正在吃香蕉");
    }
}

与之对应的工厂

AppleFactory.class

1
2
3
4
5
6
public class AppleFactory implements  Factory {
    @Override
    public Food create() {
        return new Apple();
    }
}

BananaFactory.clsss

1
2
3
4
5
6
public class BananaFactory implements  Factory{
    @Override
    public Food create() {
        return new Banana();
    }
}

工厂方法调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args) {
 
      Food food =null;
 
      Factory factory =null;
 
      /****************/
      String foodName="Apple";
      switch (foodName){
 
          case "Apple":factory =new AppleFactory();break;
          case "Banana":factory =new BananaFactory();break;
          default:factory =null;
      }
      /***************/
 
      food =factory.create();
 
      food.eat();
  }

在调用方法上仍然扩展性不足,但是可以采取反射技术弥补

运行结果:

优点:(1)与简单工厂相比,提高了工厂的扩展性,符合开放封闭原则;

缺点:(2)实现起来较之于简单工厂复杂,无法生存一系列产品

三.抽象工厂

抽象工厂是对于产品系列而言

比如衣服分为帽子,T恤从种类上分,从品牌的角度分为LiNing,Nike,针对这种情况需要创建一个产品族的对象,可以采取抽象工厂的方法

以此为思路,创建的抽象工厂UML为:

 

 

具体代码实现

Hat接口

1
2
3
4
//帽子
public interface Hat {
     void put();
}

Shirt接口

1
2
3
4
//T恤
public interface Shirt {
    void wear();
}

Shop接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface Shop {
 
    Hat SellHat();
 
    Shirt SellShirt();
 
    static Shop setShop(String typeName){
 
        try {
            Class c =Class.forName(typeName);
 
            Shop shop=(Shop) c.newInstance();
 
            return shop;
        }catch (Exception e) {
            throw new RuntimeException();
        }
    }
}

LiNingHat.class帽子类

1
2
3
4
5
6
public class LiningHat implements   Hat {
    @Override
    public void put() {
        System.out.println("穿上李宁的帽子");
    }
}

LiNingShirt.clas李宁的T恤

1
2
3
4
5
6
7
public class LiningShirt implements Shirt {
 
    @Override
    public void wear() {
        System.out.println("穿上李宁的T桖");
    }
}

Nike的帽子NikeHat.class

1
2
3
4
5
6
public class NikeHat implements Hat{
    @Override
    public void put() {
        System.out.println("穿上耐克的帽子");
    }
}

Nike的T恤NikeShirt.class

1
2
3
4
5
6
public class NikeShirt implements   Shirt{
    @Override
    public void wear() {
        System.out.println("穿上耐克的T桖");
    }
}

李宁的商店LiNingShop.class

1
2
3
4
5
6
7
8
9
10
11
12
public class LiningShop implements   Shop{
 
    @Override
    public Hat SellHat() {
        return new LiningHat();
    }
 
    @Override
    public Shirt SellShirt() {
        return new LiningShirt();
    }
}

Nike的商店NikeShop.class

1
2
3
4
5
6
7
8
9
10
11
12
//Nike商店
public class NikeShop implements   Shop {
    @Override
    public Hat SellHat() {
        return new NikeHat();
    }
 
    @Override
    public Shirt SellShirt() {
        return new NikeShirt();
    }
}

调用抽象工厂的过程

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
        Hat hat =null;
        Shirt shirt =null;
 
        Shop shop =Shop.setShop("v3.LiningShop");
 
        hat =shop.SellHat();
        shirt =shop.SellShirt();
 
        hat.put();
        shirt.wear();
    }

调用结果:

 

优点:可以针对一系列对象

确定:只针对一系列对象

总结:

简单工厂:针对同一级别的不同对象(扩展性较差)

工厂方法:针对同一级别的固定对象(开放修改接口,扩展性好)

抽象工厂:针对不同系列的全部对象(不支持单个产品扩展,只支持产品族扩展)

使用总结:(1)工厂模式中,工厂类采取的单例模式

     (2)工厂类的基类可以是接口也可以是抽象类

     (3)调用工厂采取的是指针和引用

posted @   coder-zhou  阅读(312)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示