工厂模式

Posted yl0604

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了工厂模式相关的知识,希望对你有一定的参考价值。

简介

工厂模式是java中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同接口来指向新创建的对象,其意思是代码编写出来是为了给别人调用的:

  • 调用者跟代码编写者可能是同一个人,也可能是不同人
  • 提供给调用者的代码,有可能是源码可见的,也可能是源码不可见、不可修改的(比如jar包)

所以,为了简化代码的协作使用及管理维护,必须想尽办法简化代码逻辑,实现必要的分离。

1、最原始的方式

比如说,创建不同品牌的手机

// 苹果品牌手机类
public class Iphone {
    public void xxx () {
        System.out.println("我是苹果手机");
    }
}

//华为品牌手机类
public class Huawei {
    public void yyy () {
        System.out.println("我是华为手机");
    }
}

.......

 

如果这样的代码提供给客户端调用,那么提供者必须要将所有类的名称以及对应方法暴露给客户端。

客户端的调试如下:

Iphone phone1 = new Iphone();
phone1.xxx();        // 输出:我是苹果手机

Huawei phone2 = new Huawei();
phone2.yyy();        // 输出:我是华为手机

这样的方式非常原始,也很简单,但是代码逻辑不清晰,暴露的内容过多。

解决的方案:

  • 抽象逻辑,提供接口
  • 2、有了接口之后

为了减少方法调用的复杂度,也为了便于抽象跟代码管理,提供一个接口:

public interface Phone {
    void play();
}

然后,将所有手机类都实现Phone接口,将暴露给客户端调用的逻辑都封装在play方法里;

public class Iphone implements Phone{

  @Override
  public void play() {
      System.out.println("苹果手机");
  }
}

......

 

那么客户端需要知道的调用API就减少到了两种:

  1. Phone接口的信息
  2. Phone接口有哪些实现类
Phone phone = new Iphone();
phone.play();
phone=new Huawei(); phone.play();

这种方式有缺点:

  1. 客户端,必须要知道手机类的具体名字
  2. 客户端的调用,跟提供的代码是耦合的(服务端代码的更改,客户端的代码也要跟着改,比如:我们将IPhone类改为IPhonex,那么客户端那边也要跟着改)

所以,自然产生了简单工厂的这种策略

3、简单工厂

在中间加一层:

public class PhoneFactory {
    public Phone createPhone(String tag) {
        if (tag.equals("pg")) {
            return new IPhone();
        } else if (tag.equals("hw")) {
            return new Huawei();
        }else {
            return null;
        }
    }
}

客户端的调用

PhoneFactory pf = new PhoneFactory();
pf.createPhone("hw").play();
pf.createPhone("pg").play();

简单工厂模式,本身已经为解耦合做出来很好的方案。但是它有缺点:

  • PhoneFactory  代码跟Phone代码紧耦合
  • 每次添加/删除/修改某一个Phone ,都需要修改PhoneFactory这个类

解决方案就是工厂方法模式

4、工厂方法模式

为Phone工厂,创建一个接口:

public interface PhoneFactory {
    Phone createPhone();
}

如果增加了一款产品,比如是iPone,那么,只需要为iPhone创建一个工厂类就可以了

 

public class IphoneFactory implements PhoneFactory {
    public phone createPhone() {
        return new IphoneX();
    }
}

 

如果再增加另外一款产品,比如Huawei,那么只需要另外一个工厂就可以了
public class HuaweiFactory implements PhoneFactory {
    public phone createPhone() {
        return new Huawei();
    }
}
客户端的调用:
PhoneFactory hwPf = new HuaweiFactory();
hwPf.createPhone().play();

PhoneFactory pgPf = new IphoneFactory();
pgPf.createPhone().play();

工厂方法模式,是最标准的一种工厂模式,也是应用广泛的一种模式。

但是工厂方法模式,有一个很大的缺点:

  • 代码容易膨胀
  • 不容易反映产品与产品之间的关系

5、抽象工厂

public interface PhoneFactory {
    Phone createPhone();
    Usb createUSB();
    Charger createCharger();
}

华为手机:

public class HuaweiPhoneFactory implements PhoneFactory {
    Phone createPhone() {
        return new HuaweiPhone();
    }
    Usb createUSB() {
        return new HuaweiUSB();
    }
    Charger createCharger() {
        return new HuaweiCharger();
    }
}

// ...
客户端调用:
PhoneFactory pf = new HuaweiPhoneFactory();
pf.createPhone();
pf.createUsb();
pf.createCharger();

// 通过一个工厂,把一个族中的相关产品全都输出来了

 

 







以上是关于工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式学习——简单工厂模式工厂模式抽象工厂模式

设计模式简单工厂模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

设计模式学习——简单工厂模式工厂模式抽象工厂模式

设计模式工厂方法模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

设计模式-简单工厂工厂方法模式抽象工厂模式详解

C++工厂模式(简单工厂工厂方法抽象工厂)