首页 > 其他分享 >工厂模式案例解释

工厂模式案例解释

时间:2022-11-10 22:57:49浏览次数:46  
标签:解析器 String 代码 模式 工厂 案例 new public

1.1 工厂模式

​ 工厂模式一般分为简单工厂、工厂方法、抽象工厂,那么什么是简单工厂模式?工厂方法?抽象工厂模式?先看例子,再去看概念和UML图。

举例:
   假设现在有一个项目要进行文件解析,需要根据文件的类型,去使用不同的文件解析器,比如json类型的文件需要用Json解析器,xml类型文件使用xml解析器等。

定义:

  1. 首先定义一个解析器接口:

    public interface ITypeParser{
    	void parse(String text);
    }
    
  2. 再定义具体的解析器类JsonTypeParser:

    public class JsonTypeParser implements ITypeParser{
            @Override
            public void parse(String text) {
                System.out.println("json解析器");
            }
        }
    
  3. 再定义具体的解析器类XmlTypeParser:

     public class XmlTypeParser implements ITypeParser{
            @Override
            public void parse(String text) {
                System.out.println("xml解析器");
            }
        }
    

1.1.1 不使用工厂模式

​ 如果不使用工厂模式,我们一般的写法就是这样:

public class NonFactoryPattern {

    public static void main(String[] args) {
        /**
         * 不使用工厂模式
         */
        File file = new File("D:/com/..");
        String fileName = file.getName();
        String fileExtension = fileName.substring(fileName.lastIndexOf('.'));

        ITypeParser iTypeParser = null;
        if(fileExtension.equalsIgnoreCase("json")){
            iTypeParser = new JsonTypeParser();
        }else if(fileExtension.equalsIgnoreCase("xml")){
            iTypeParser = new XmlTypeParser();
        }

        iTypeParser.parse("");
    }
}

从上面的代码中可以看出一些问题:
(1)获取文件解析器对象的代码写在main方法中,即业务方法中,若在同一个业务里,需要多次用到文件解析器,那岂不是很多地方都有重复的代码块。
(2)获取解析器对象都在if-else中,如果要增加一个两个,那又得写出一个两个if-else,可见代码的扩展性不好。
    
    
那怎么解决上诉问题呢?
    就是把获取解析器的代码写到一个类里,这样在业务方法中需要的时候直接调用这个类就好了。并且要扩展多个解析器的时候,只需要在那个类里修改就好了,不影响业务代码。-----> 简单工厂方法

1.1.2 简单工厂方法

​ 使用简单工厂方法的代码如下:

业务代码:

//这个工厂只负责创建解析器对象
public class EasyFactory {
    public ITypeParser getTypeParser(String fileExtension){
        ITypeParser iTypeParser = null;
        if(fileExtension.equalsIgnoreCase("json")){
            iTypeParser = new JsonTypeParser();
        }else if(fileExtension.equalsIgnoreCase("xml")){
            iTypeParser = new XmlTypeParser();
        }else if(fileExtension.equalsIgnoreCase("properties")){  //新增一个
//            iTypeParser = new PropertiesTypeParser();
        }
        return iTypeParser;
    }
}
从上面的代码我们可以看到一个问题:
每次增加一个解析器,是需要在这个工厂类里去添加一个if-else,即需要修改这个类中的代码,违反了开闭原则(对扩展开放,对修改关闭)。

那有什么办法解决呢?
	可以给每个解析器都自己常见一个工厂,每个工厂都只负责创建自己的解析器,如XMLFactory只负责创建XmlTypeParser解析器。这就是工厂方法,即一个工厂下有多个具体工厂,每个工厂负责创建不同的产品。

1.1.3 工厂模式

​ 将解析器的获取放在该解析器对应的具体的工厂中进一步解耦,这个时候如果需要扩展一个新的解析器,只需要再增加一个实现ITypeParserFactory的实现类就可以了,工厂方法模式比简单工厂模式更符合开闭原则。

  1. 定义一个工厂接口ITypeParserFactory :

    public interface ITypeParserFactory {
        ITypeParser getParser();
    }
    
  2. 具体的工厂JsonTypeParserFactory:

    public class JsonTypeParserFactory implements ITypeParserFactory{
        @Override
        public ITypeParser getParser() {
            return new JsonTypeParser();
        }
    }
    
  3. 具体的工厂XmlTypeParserFactory:

    public class XmlTypeParserFactory implements ITypeParserFactory{
    
        @Override
        public ITypeParser getParser() {
            return new XmlTypeParser();
        }
    }
    
  4. 业务代码:

    public static void main(String[] args) {
            /**
             * 使用工厂方法
             */
            File file = new File("D:/com/..");
            String fileName = file.getName();
            String fileExtension = fileName.substring(fileName.lastIndexOf('.'));
    
            ITypeParserFactory iTypeParserFactory = null;
            if(fileExtension.equalsIgnoreCase("json")){
                iTypeParserFactory = new JsonTypeParserFactory();
            }else if(fileExtension.equalsIgnoreCase("xml")){
                iTypeParserFactory = new XmlTypeParserFactory();
            }
    
            iTypeParserFactory.getParser();
        }
    
    上面的业务代码看起来和没有使用工厂模式的代码差不多一样,但是仔细看,工厂方法中使用的是ITypeParserFactory,也就是使用的是工厂类,一般在业务代码中获取解析器的工厂对象是可以复用的,所以当使用更多的解析器时,可以直接使用iTypeParserFactory对象去获取解析器就可以了。
        
        
    如果现在需要根据环境或其他因素选择解析器呢?
        可以使用抽象工厂方法。
    

1.1.4 抽象工厂

​ 简单工厂和工厂方法中,解析器只有一种分类方式,根据文件类型解析(json,xml等)。如果现在还需要根据文件环境来分类,如(开发环境,测试环境)或根据权限分类,如(管理员,普通用户)等。针对这种场景,如果使用工厂方法模式,需要针对每个parser编写工厂类,这样会产生大量的类,所以可以选择使用抽象工厂。

public interface IParserFactory {
    ITypeParser getTypeParser();
    IEnvParser getEnvParser();
}
在抽象工厂中创建一个根据环境选择解析器的方法,这样具体工厂实现抽象工厂时,就有相应的方法去提供了。

1.1.5 概念

  1. 简单工厂方法:

    将业务代码中创建对象的复杂逻辑代码抽取到一个类中,但其不符合开闭原则,不常使用。
    
  2. 工厂模式:

    (1)意图:定义一个创建对象(创建对象的工厂)的接口,让具体的工厂类去实现接口,将创建对象的过程延申到了子类。
    (2)主要解决:接口选择问题。
    (3)何时使用:计划在不同条件下使用不同的产品(创建不同的实例)。
    (4)如何解决:让子类(具体的工厂)去实现工厂接口,返回一个抽象产品。
    (5)优点:
        扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 
        屏蔽产品的具体实现,调用者只关心产品的接口。
    (6)缺点:
        每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
    
  3. 抽象工厂:

(1)意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。(即可根据文件类型又需要根据环境选择不同的文件解析器)
(2)主要解决:接口选择问题。
(3)何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。(文件解析器即需要根据文件类型去选择,又需要根据环境去选择。又如所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。)
(4)如何解决:在一个产品族里面,定义多个产品。
(5)优点:
    当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
(6)缺点:
    产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。

1.1.6 工厂模式的好处

(1)封装变化:创建逻辑有可能变化,封装成工厂类之后,创建逻辑的变更对调用者透明。
(2)代码复用: 创建代码抽离到独立的工厂类之后可以复用。
(3)隔离复杂性:封装复杂的创建逻辑,调用者无需了解如何创建对象
(4)控制复杂度:将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。

标签:解析器,String,代码,模式,工厂,案例,new,public
From: https://www.cnblogs.com/lxpblogs/p/16879079.html

相关文章

  • 14.严格模式
    严格模式JS运行代码的模式有两种:正常模式默认情况下代码都运行在正常模式下在正常模式,语法检查并不严格它的原则是,能不报错的地方尽量不报错这种处理方式导致代码......
  • ht 中Data案例1
    <!DOCTYPEhtml><html><head><title>Data</title><metacharset="UTF-8"><style>html,body{padding:0px;margin:0px;}.main{margin:0px;padding:0px;......
  • [DPDK] 混杂模式
    [DPDK]混杂模式通常来讲,当一个网卡收到的包的目标MAC地址不是这个网卡的MAC地址时,网卡会无视这个包。如果想让网卡可以收到destMAC是任意地址的包,需要开启DPDK的混杂模......
  • 浅谈PHP设计模式的模板方法模式
    简介:模板方法模式,是行为型的设计模式。定义一个操作中的算法的骨架,而将一些步骤延迟到子类当中,使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。通......
  • Spring与Struts2的整合案例及XML配置的具体使用(四)
    东家蝴蝶西家飞,白骑少年今日归。愿,所有迷茫的人,都不再迷茫的,愿,所有努力工作的人,都可以得到应有的回报,愿,所有的人,都可以找到回家的方向,愿,再无苦痛,再无离别。上一章简单介绍......
  • 设计模式学习(九):装饰器模式
    设计模式学习(九):装饰器模式作者:Grey原文地址:博客园:设计模式学习(九):装饰器模式CSDN:设计模式学习(九):装饰器模式装饰器模式装饰器模式是一种结构型模式。顾名思义,就是对某......
  • 浅谈PHP设计模式的原型模式
    简介:原型模式,属于创建型模式的一种。主要针对对象进行克隆,把被克隆的对象称之为原型,原型模式称之为克隆模式也许更为贴切。用原型实例指定创建对象的种类,并且通过拷贝这......
  • 23.策略模式
    [实验任务一]:旅行方式的选择旅游的出行方式有乘坐飞机旅行、乘火车旅行和自行车游,不同的旅游方式有不同的实现过程,客户可以根据自己的需要选择一种合适的旅行方式。代码......
  • Java零基础-面向对象入门案例:宠物商店
    Java零基础-面向对象入门案例:宠物商店案例需求:设计宠物类,包含有:编号、名称、年龄、种类、性别、是否防疫等信息,设计宠物商店,实现宠物添加、删除、修改宠物信息,记录宠物......
  • 【爱卡不卡】单身状态:开启归属感模式
    9月21日爱卡不卡昨天简书心理群开始了一个活动叫“爱卡不卡”,首次进去,还没熟知玩法,后来才知道,心理群组专门给了一组图片,图片中的三张图分别表现了三种不同的状态,当时看到......