工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
工厂模式分为三种:简单工厂模式、工厂方法模式、抽象工厂模式。
一、简单工厂模式<对象抽离接口>
简单工厂模式适用于工厂类负责创建的对象比较少的情况,并且 客户端只需要传入工厂类的参数,不需要关心创建对象的细节。
1、创建接口对象
// 创建手机接口对象
public interface Phone{
// 定义一个发送信息的接口
public void send();
}
2、创建SmartPhone对象,并实现接口
public class SmartPhone implements Phone{
@Override
public void send() {
//智能机可以发微信
System.out.println("智能手机发微信");
}
}
3、创建OldMachine对象,并实现接口
public class OldMachine implements Phone{
@Override
public void send() {
//老年机只能发短信
System.out.println("老年机发短信");
}
}
4、创建工厂类Factory
public class Factory{
public Phone createPhone(String type){
if("smartPhone".equals(type)){
return new SmartPhone();
}else if("oldMachine".equals(type)){
return new OldMachine();
}
return null;
}
}
5、编写测试类
public class Test {
public static void main(String[] args){
Factory factory=new Factory();
Phone phone_1=factory.send("oldMachine");
phone_1.send();
Phone phone_2=factory.send("smartPhone");
phone_2.send();
}
}
打印结果为:
老年机发短信
智能手机发微信
以上虽然实现了由自己创建对象改为由工厂创建对象,但是存在一个问题,如果需要增加一个儿童手机【为了孩子们的健康,只能让他打电话、发短信】,那么如果我们还想使用工厂模式创建对象,只能是修改Factory工厂类,这样的话就违反了我们的开闭原则,对于项目的扩展也是不利的,由此引出了工厂方法模式。
二、工厂方法模式<工厂抽离接口>
1、首先我们先创建一个工厂接口
public interface Factory{
public Phone createPhone();
}
2、创建一个智能手机工厂,并实现工厂接口
public class SmartPhoneFactory implements Factory{
@Override
public Phone createPhone(){
return new SmartPhone();
}
}
3、创建一个老年机工厂,并实现工厂接口
public class OldMachineFactory implements Factory{
@Override
public Phone createPhone(){
return new OldMachine();
}
}
4、创建测试类
public class Test {
public static void main(String[] args){
Factory factory=new SmartPhoneFactory();
Phone phone=factory.createPhone();
phone.send();
}
}
5、控制台打印结果
智能手机发微信
对于工厂方法模式,则规避了开闭原则,如果有新的手机加入的话,我们只需要为其再创建一个工厂就可以了,感觉是不是比第一个更利于扩展。但此方法仍然有一个比较严重的问题,就是当我们的对象非常多的时候,那么对应的工厂也就十分庞大,无疑是增加代码的复杂度。
当然还有多个工厂方法,即一个工厂类中含有创建多个对象的方法。此方法也是违背了开闭原则,所以就不在讨论。
三、抽象工厂模式<对象及工厂抽离为接口>
1、定义手机接口
public interface Phone {
public void send();
}
2、智能手机实现类
public class SmartPhone implements Phone {
@Override
public void send() {
System.out.println("智能手机发微信");
}
}
3、老年机实现类
public class OldMachine implements Phone{
@Override
public void send() {
System.out.println("老年机发短信");
}
}
4、工厂接口类
public interface Factory {
public Phone createPhone();
}
5、智能手机工厂实现类
public class SmartPhoneFactory implements Factory {
@Override
public Phone createPhone() {
return new smartPhone();
}
}
6、老年机工厂实现类
public class OldMachineFactory implements Factory {
@Override
public Phone createPhone() {
return new oldMachine();
}
}
7、测试类
public class Test {
public static void main(String[] args){
Factory factory= new SmartPhoneFactory();
Phone phone=factory.createPhone();
phone.send();
}
}
测试结果为:
智能手机发微信
由此,抽象工厂模式已经结束,如果有新增的产品只需要增加产品实现类及该产品的工厂实现类就可以了。但是如果该产品需要增加一个新功能call 那么还是需要修改源代码,也是不符合开闭原则。当然有时我们不需要严格按照开闭原则来做,只要产品不频繁升级,根据实际情况可以不遵守开闭原则,比如说每年升级一次,又有何不可呢?