工厂方法模式定义
工厂模式的英文原话是:
Define an interface for creating an object,but let subclasses decide which class to instantiate.Factory Method lets a class defer instantiation to subclass.
意思是:定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
这段话大家都懂,但为什么要这样做呢?下面我用一个例子来讲解一下
看一下简单工厂模式是怎样的,先看代码
public class Demo1 {
public static void main(String[] args) {
IFruit apple = FruitFactory.createFruit("Apple");
apple.info();
IFruit orange = FruitFactory.createFruit("Orange");
orange.info();
}
}
class FruitFactory{
public static IFruit createFruit(String fruitName){
IFruit iFruit = null;
switch (fruitName){
case "Apple":
iFruit = new Apple();
break;
case "Orange":
iFruit = new Orange();
break;
}
return iFruit;
}
}
interface IFruit{
void info();
}
class Apple implements IFruit{
@Override
public void info() {
System.out.println("我是苹果..");
}
}
class Orange implements IFruit{
@Override
public void info() {
System.out.println("我是橘子..");
}
}
为了方便观看,我把所有的类/接口都放在一起了
IFruit接口:水果接口
Apple 、Orange :水果接口的实现类
FruitFactory:生产水果的工厂类
FruitFactory的createFruit方法根据传递不同的参数来创建不同的水果,这便是简单工厂模式
那么简单工厂模式的缺点是什么呢?
当我们想要让FruitFactory水果工厂去生产香蕉呢,这时该怎么办?
因为水果类的接口是IFruit,所以想要扩展一个香蕉类很容易
class Banana implements IFruit{
@Override
public void info() {
System.out.println("我是香蕉..");
}
}
有了Banana 之后,接下来需要修改FruitFactory水果工厂了
class FruitFactory{
public static IFruit createFruit(String fruitName){
IFruit iFruit = null;
switch (fruitName){
case "Apple":
iFruit = new Apple();
break;
case "Orange":
iFruit = new Orange();
break;
case "Banana":
iFruit = new Banana();
break;
}
return iFruit;
}
}
可以看到我们新增了case "Banana"
判断
这样直接去修改FruitFactory类显然违背了开闭原则
,对扩展开放、对修改关闭
如果对设计原则不太清楚,传送门六大设计原则 每新增一个水果都要去修改FruitFactory工厂类,加多了不仅内容冗余,而且不易维护
那么如何去优化这个问题呢?接下来就引出了今天的主角工厂方法模式
定义一个用于创建对象的接口
工厂类接口IFruitFactory
interface IFruitFactory{
IFruit createFruit();
}
让子类决定实例化哪个类
class AppleFactory implements IFruitFactory{
@Override
public IFruit createFruit() {
return new Apple();
}
}
class OrangeFactory implements IFruitFactory{
@Override
public IFruit createFruit() {
return new Orange();
}
}
来看一下完整Demo
public class Demo2 {
public static void main(String[] args) {
IFruitFactory appleFactory = new AppleFactory();
IFruit apple = appleFactory.createFruit();
apple.info();
IFruitFactory orangeFactory = new OrangeFactory();
IFruit orange = orangeFactory.createFruit();
orange.info();
}
}
interface IFruitFactory{
IFruit createFruit();
}
class AppleFactory implements IFruitFactory{
@Override
public IFruit createFruit() {
return new Apple();
}
}
class OrangeFactory implements IFruitFactory{
@Override
public IFruit createFruit() {
return new Orange();
}
}
输出结果
我是苹果..
我是橘子..
那我们如果需要生产香蕉banana该怎么办呢?
只需要创建BananaFactory即可
class BananaFactory implements IFruitFactory{
@Override
public IFruit createFruit() {
return new Orange();
}
}
无需修改原有的类,只需扩展一个BananaFactory 类,符合开闭原则
IFruitFactory依赖的是IFruit 也符合接口隔离原则
,降低耦合,便于扩展
看到了这里,可能有人要问了我要Apple类直接new Apple()不就完了,干嘛还要先创建一个工厂,再通过工厂去创建Apple呢?
如果仅仅是new Apple()确实是不需要这么做,但是如果还需要为Apple对象添加一些属性呢,比如setColor设置颜色,这个例子不太直观
原生jdbc想必大家都有写过吧,需要设置连接url、用户名、密码、驱动类,如果每次获取数据库连接都需要这么操作,那岂不是到处都是这些重复代码,所以这里也会用到工厂类,不仅生产连接数据库对象而且还会将连接url、用户名、密码等参数封装到对象中,这样我们只需要使用工厂类即可,不需要去管连接数据库对象是如何创建的细节
工厂方法模式的优点良好的封装性
一个对象的创建是有条件约束的,如果一个调用者需要一个具体的产品对象,只要知道这个产品的类名或约束字符串即可,不用知道创建对象的过程如何,降低了模块间的耦合。优秀的扩展性
在增加产品类的情况下,只要适当地修改具体的工厂类或扩展一个工厂类就可以适应变化
以上就是工厂方法模式的全部内容了
如有不妥,欢迎指点
如有帮助到你,欢迎点个赞再走