什么是“工厂方法模式”
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
我们来看看工厂方法模式的UML图:
从类图中我们可以看到,工厂方法有两个平行的接口(抽象类),一个是Product,一个是Factory。
他们具体什么意思呢, 我们可以先来看看例子,然后再理解这个类图。
为什么要使用“工厂方法模式”
背景:假如我们需要使用 Java 生产很多款手机, 那么我们最传统最简单的做法似乎是这样子:
public Phone createPhone(String name){
if (name.equals("小米")){
phone = new XiaoMiPhone();
}else if (name.equals("华为")){
phone = new HuaWeiPhone();
}else if (...)
}
这样做貌似没什么不对,但是我们可以仔细想想,假如我们需要生产更多品牌的手机呢?再加入我们需要不同国家生产适合该国家的手机呢(比如港版、美版等等)? 出现这类需求的时候, 我们这么做就显得有些力不从心了。
这个时候, 工厂方法模式就该登场了。
如何使用“工厂方法模式”
-
根据类图,我们首先需要两个顶层的接口
/** * 手机的抽象类 * */ public abstract class Phone { public String name; public double price; public abstract void showPhone(); } /** * 工厂的抽象类 * */ public abstract class PhoneFactory { public abstract Phone createPhone(String name); }
-
有了顶层接口,我们需要具体的手机类
//华为 public class HuaWeiPhone extends Phone { public HuaWeiPhone(String name, double price) { super.name = name; super.price = price; } @Override public void showPhone() { System.out.println("华为被生产出来啦============="); System.out.println(name + ": " + price); } } //小米 public class XiaoMiPhone extends Phone { public XiaoMiPhone(String name, double price) { super.name = name; super.price = price; } @Override public void showPhone() { System.out.println("小米被生产出来啦============="); System.out.println(name + ": " + price); } } //Iphone public class IPhone extends Phone { public IPhone(String name, double price) { super.name = name; super.price = price; } @Override public void showPhone() { System.out.println("苹果被生产出来啦============="); System.out.println(name + ": " + price); } }
-
有了具体的手机类之后,我们就可以把具体的工厂创建出来了
/** * 某个国家的工厂 */ public class PhoneFactoryImpl extends PhoneFactory { Phone phone; @Override public Phone createPhone(String name) { if (name.equals("华为")){ phone = new HuaWeiPhone(name,3999.99); }else if (name.equals("小米")){ phone = new XiaoMiPhone(name,2999.99); }else if (name.equals("苹果")){ phone = new IPhone(name,6999.99); } return phone; } }
在这个方法中,其实可以使用反射技术实现在运行时动态地创建相应的对象,这样就可以在新增某款手机的时候避免修改代码。但是为了简单起见,我们在这里不使用反射技术,直接使用原始的方法。
-
所有东西都准备齐全了, 我们可以生产手机了。
public class CreatePhoneTest { public static void main(String[] args){ Phone phone; PhoneFactory factory = new PhoneFactoryImpl(); phone = factory.createPhone("小米"); phone.showPhone(); phone = factory.createPhone("苹果"); phone.showPhone(); phone = factory.createPhone("华为 "); phone.showPhone(); } }
-
运行结果如下:
小米被生产出来啦============= 小米: 2999.99 苹果被生产出来啦============= 苹果: 6999.99 华为被生产出来啦============= 华为: 3999.99
在这个例子中, 我们只实现了一种具体的工厂, 假如需要不同的工厂生产不同类型的手机, 工厂方法模式无疑提供了很大的便利和可拓展性。
那么, 总结来了
在上面的例子中, 我想各位同学也都理解了UML类图的具体含义。
工厂方法模式是一种很实用、 拓展性强的模式。
优点:
封装性强: 我们只需要知道某个手机类或者手机名字的约束字符串,就可以进行生产。(本例中还需要去工厂实现类中添加一个判断分支,在具体的应用场景中我想没人会使用判断分支在工厂类中,一般都是使用反射)
拓展性好:比如我们还需要增加一款魅族手机,那么我们只需要实现 MeiZuPhone 类就可以了。
屏蔽了产品类:这一点非常有用,屏蔽了手机内部的具体实现, 只需要知道他们实现了 Phone 接口就行了。
使用场景:
工厂方法模式是 new 一个对象的替代品, 所以在需要新建一个对象的时候都可以使用, 但是要考虑使用后代码的复杂度。
与工厂方法模式类似的抽象工厂模式将在下一篇文章发表。欢迎关注
感谢阅读本博客。
欢迎关注我的博客:https://li-weijian.github.io/
欢迎关注我的CSDN:https://blog.csdn.net/qq352642663
需要联系请加QQ:352642663
欢迎联系我共同交流