zoukankan      html  css  js  c++  java
  • 设计模式-工厂模式

    工厂模式

     当我们创建一个对象比较复杂时且客户端不关心于实例对象的创建过程时我们可以用工厂模式

    类型:

    • 简单工厂模式

    • 工厂方法模式

    • 抽象工厂模式

       

    简单工厂模式

    百度百科

    简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现

    下面我们来举一个例子:

    比如我们一个手机可能有苹果、华为、小米这些品牌的手机,手机里面又有很多零件,如果当一个手机的类定义是这样的

    public class Mobile implements IMobile{
    ​
        //CPU
        private String cpu;
        //内存
        private String memory;
        //显示屏
        private String display;
    ​
    ​
        public Mobile(String cpu, String memory, String display) {
            this.cpu = cpu;
            this.memory = memory;
            this.display = display;
        }
        public void show() {
                System.out.println(this.getDisplay() + " show...");
        }   
    }

     

    手机类实现了一个接口IMobile 这个接口有一个方法show();

    如果我们不用工厂模式呢可能我们生产一个手机是这样的:

    IMobile mobile = new Mobile("苹果cpu","苹果内存","苹果显示器");
    mobile.show();

    如果这样的话我们使用者就需要知道我们创建一个Mobile需要传入什么参数,但如果我们使用简单工厂模式的话就比较简单了,首先我们定义一个工厂类:

    public class MobileFactory {
    ​
        IMobile create(String name){
            if("iphone".equals(name)){
                return new Mobile("苹果cpu","苹果内存","苹果显示器");
            }else if("xiaomi".equals(name)){
                return new Mobile("小米cpu","小米内存","小米显示器");
            }else{
                return null;
            }
        }
    }

    该工厂类有一个创建方法,参数接受一个手机品牌的名称,然后我们返回一个相应的手机实例,创建实例需要的参数我们在方法里定义好,这样我们客户端在创建手机实例的时候只需要传入相应的品牌名称就好了,不需要关心创建的逻辑和实现也就是我们例子中的所需要的参数:

    public static void main(String[] args) {
        MobileFactory factory = new MobileFactory();
        IMobile mobile = factory.create("iphone");
        mobile.show();
    }

    这个就是我们的简单工厂模式了,但是如果使用了简单工厂的话我们来想下如果当我要新增一个产品的话要怎么办呢,比如我现在要新增一个华为手机,那我们就需要在简单工厂中修改创建方法的逻辑,增加一个华为品牌的创建逻辑,这样就不符合我们的开闭原则了,同时如果我们的品牌非常多的话创建方法就会太复杂太重了,这样不利于我们的维护。

    优缺点

      优点:

        只需传入一个工厂类的参数,无需关心我们的创建流程

      缺点:

        工厂类的职责过重,新增产品需要修改工厂类的方法,违背了我们的开闭原则,不易于扩展比较复杂的产品结构

     

    适合场景

    工厂类只需要创建很少的对象,客户端不需要传入工厂参数,不需要关心创建流程

     


     

    工厂方法模式

    维基百科

    工厂方法模式(英语:Factory method pattern)是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题。工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行

     

    工厂方法模式是可以用来解决我们上面简单工厂模式的缺点的,工厂方法模式是简单工厂的一个升级,我们还是用上面的例子来看下工厂方法模式是怎么实现的,首先,我们先定义一个工厂类的接口:

    public interface IMobileFactory {
          
        IMobile create();
    }

    该接口只有一个方法create,返回一个手机实例,我们再来根据品牌创建一个工厂接口的实现类,我们先创建一个苹果品牌的实现类:

    public class IPhoneFactory implements IMobileFactory {
        
        public IMobile create() {
            return new Mobile("苹果cpu","苹果内存","苹果显示器");
        }
    }

    这样我们的客户端在使用的时候只需要指定具体的工厂类就可以了:

    public static void main(String[] args) {
        IMobileFactory factory = new IPhoneFactory();
        IMobile mobile = factory.create();
        mobile.show();
    }

    如果我们需要新增品牌的时候只需要增加新的品牌工厂就行了,比如我们来新增小米的工厂类:

    public class XiaoMiFactory implements IMobileFactory {
    ​
        public IMobile create() {
            return new Mobile("小米cpu","小米内存","小米显示器");
        }
    }
    ​
    ​
    public static void main(String[] args) {
            IMobileFactory factory = new XiaoMiFactory();
            IMobile mobile = factory.create();
            mobile.show();
        }

    这样我们就避免了新增产品的时候需要去修改工厂方法了,符合了我们的开闭原则。

    优缺点

      优点:

        不需要关心产品的创建流程,只需关心产品对应的工厂,新增产品时易于扩展,符合开闭原则

      缺点:

        当品牌过多的时候会生成过多的工厂类,增加了代码结构的复杂性,增加系统的抽象性,不易于理解

    适用场景

    创建对象需要大量的重复代码时,不关心创建细节,通过子类去指定创建哪个对象

     


     

    抽象工厂模式

    维基百科

    抽象工厂模式(英语:Abstract factory pattern)是一种软件开发设计模式。抽象工厂模式提供了一种方式,可以将一组具有同一主题的单独的工厂封装起来。在正常使用中,客户端程序需要创建抽象工厂的具体实现,然后使用抽象工厂作为接口来创建这一主题的具体对象。客户端程序不需要知道(或关心)它从这些内部的工厂方法中获得对象的具体类型,因为客户端程序仅使用这些对象的通用接口。抽象工厂模式将一组对象的实现细节与他们的一般使用分离开来。

    我们还是按上面的例子来说,比如现在我们的苹果和小米不止有手机了,还有其对应的笔记本电脑、运动手环啊之类的,这样每个品牌下都有自己对应的产品,我们就可以用抽象工厂来实现,首先我们还是创建一个工厂接口,该接口下有对应的创建产品的方法:

    public interface IMobileFactory {
        //生产手机
        IMobile createMobile();
        //生产电脑
        IComputer createComputer();
        //生产手环
        IBracelet createBracelet();
    }

    接下来我们就要来实现对应品牌下的工厂类:

     

    public class IPhoneFactory implements IMobileFactory{
    ​
        public IMobile createMobile() {
            return new Mobile("苹果cpu","苹果内存","苹果显示器");
        }
    ​
        public IComputer createComputer() {
            return new Computer("苹果");
        }
    ​
        public IBracelet createBracelet() {
            return new Bracelet("苹果");
        }
    }
    ​
    ​
    public class XiaoMiFactory implements IMobileFactory {
    ​
        public IMobile createMobile() {
            return new Mobile("小米cpu","小米内存","小米显示器");
        }
    ​
        public IComputer createComputer() {
            return new Computer("小米");
        }
    ​
        public IBracelet createBracelet() {
            return new Bracelet("小米");
        }
    }

    这样,我们客户端在创建对应品牌下的产品的时候只需要关心对应的工厂类就可以了:

    public static void main(String[] args) {
    ​
        //苹果创建
        IMobileFactory factory = new IPhoneFactory();
        factory.createComputer().start();
        factory.createBracelet().show();
        factory.createMobile().show();
        //小米创建
        factory = new XiaoMiFactory();
        factory.createComputer().start();
        factory.createBracelet().show();
        factory.createMobile().show();
    }
     

    优缺点

      优点:

        具体创建的产品在应用层隔离,无需关心创建细节,一系列的品牌产品在统一到一起创建

      缺点:

        当品牌需要新增产品的时候,所以实现该接口的工厂类都需要修改,修改困难,需要在定义的时候先规定好产品集合

     

    适合场景

      客户端不关心产品创建细节,强调同一系列相关的产品统一到一起创建需要大量的重复代码,提供一个产品类的库,所以产品以同样的接口出现,使客户端不需要依赖具体的实现。

  • 相关阅读:
    深入理解MyBatis中的一级缓存与二级缓存
    Spring-mvc文件的上传和下载
    Spring-mvc的拦截器和异常通知
    各种配置文件
    设计模式---代理模式
    dom4j读取xml和dtd的使用方式
    几种不同的路径
    常用正则表达式
    请求转发和重定向的对比
    跨浏览器检测某个节点是不是另一个节点的后代
  • 原文地址:https://www.cnblogs.com/mori-luck/p/10634341.html
Copyright © 2011-2022 走看看