工厂模式
简介
工厂模式是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就减少到了两种:
- Phone接口的信息
- Phone接口有哪些实现类
Phone phone = new Iphone(); phone.play();
phone=new Huawei(); phone.play();
这种方式有缺点:
- 客户端,必须要知道手机类的具体名字
- 客户端的调用,跟提供的代码是耦合的(服务端代码的更改,客户端的代码也要跟着改,比如:我们将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(); // 通过一个工厂,把一个族中的相关产品全都输出来了