优缺点"/>
简单工厂模式的实现及优缺点
目录
一、开闭原则(Open Close Principle):
二、简单工厂模式的实现:
三、简单工厂模式违反了开闭原则
四、建议
一、开闭原则(Open Close Principle):
- 定义:
一个软件实体(如类、模块和函数)应该对扩展开放,对修改关闭。
就是说对于一个项目或者某个功能点,现要增加一个新的扩展功能,最好应该在不改变现有代码的前提下,植入新的代码,既不影响现有功能,又能够实现我们新增的功能,并且没有修改现有代码。
个人理解,就好比我现在想喝豆浆,并且只有黄豆,那我就需要一台豆浆机,这个豆浆机暂时把它理解为一个软件实体,突然有一天,欲望膨胀了,我又想和西瓜汁,那么我需要去准备西瓜,但是又不想再买榨汁机,想使用豆浆机来试着榨一杯西瓜汁,那么,在我不对当前的豆浆机做任何改变的前提下,能够榨出一杯西瓜汁,那么原来这台豆浆机,就符合开闭原则;如果我需要对当前豆浆机做出一些零部件的调整,才能和西瓜汁,那么就违反了开闭原则。如果不论怎么改都榨不出西瓜汁,那么就只能喝豆浆(个人意见,若有错误,请评论指出,谢谢)
-
目的
为了代码的可扩展性,并且避免了对现有代码的修改给软件带来风险。
- 先学习下面的简单工厂模式,之后我们再回来看一下,简单工厂模式是如何违反开闭原则的。
二、简单工厂模式的实现:
- 定义:定义一个工厂类,根据传入的参数的值不同,返回不同的实例(所有的实例都由仅有的这个工厂来创建)
- 特点:被创建的实例具有共同的父类或接口
- 结构:
一个用于创建实例的工厂类
一个接口,所有被创建的实例都要实现该接口
现在想定义一个工厂,用来创建不同的鼠标。上图中,分别定义了 DellMouse 和 HpMouse 且都实现了Mouse接口,同时也都实现了 Mouse 接口中的 sayHi() 方法。又创建了一个叫 MouseFactory 的工厂类,并通过调用该类的 createMouse() 方法,根据传入不同的i值,来决定创建特定类型的鼠标实例,来返回给业务层调用。
比如传入0的时候,就会返回一个DellMouse的实例,并返回。这样,便能在业务需要的时候,调用MouseFactory的静态方法createMouse(),获取我们需要的特定实例,并调用实例的sayHi方法来满足业务需求。
-
代码实现:
1.首先创建Mouse接口以及DellMouse和HpMouse,并实现sayHi方法:
三个类的具体实现如下:
//Mouse接口
public interface Mouse {public void sayHi();
}
//HpMouse类
public class HpMouse implements Mouse {@Overridepublic void sayHi() {System.out.println("我是惠普鼠标");}
}
//DellMouse类
public class DellMouse implements Mouse {@Overridepublic void sayHi() {System.out.println("我是戴尔鼠标");}
}
2.创建对应的MouseFactory工厂类,用来返回对应的工厂类
具体实现如下:
public class MouseFactory {public static Mouse createMouse(int type){switch (type){case 0 : return new DellMouse();case 1 : return new HpMouse();default:return new DellMouse();}}public static void main(String[] args) {Mouse mouse = MouseFactory.createMouse(1);mouse.sayHi();}
}
执行main方法,输出如下:
我是惠普鼠标
上面的工厂类,就实现了,根据传入不同的参数,来返回不同的实例。当前例子中,传入1,就返回HpMouse,再通过Mouse接口的sayHi方法,来调用不同实现类的sayHi方法,就实现了简单工厂模式。
在简单工厂中,隐藏了对象创建的细节,客户端不需要自己创建实例,只需要告诉工厂,需要哪个具体实现类就可以。
- 适用场景:
1.需要创建的对象比较少。
在上面的例子中,我们只是创建了两个鼠标实现类,如果需要几十个上百个具体的实现类的情况,那么在工厂类的switch或者if else语句中就要写很多行代码,很笨重。
2.客户端不关心对象的创建过程
该特点同样适用与其他工厂模式。上面的例子中,就不需要了解DellMouse或者HpMouse实例的创建过程,直接在需要的地方传入不同参数调用就好了。
- 优缺点:
- 优点:
可以对创建的对象进行“加工”,对客户端隐藏相关细节。只关注结果,无需了解过程
- 缺点:
1. 若创建逻辑复杂或创建对象过多,则会造成代码臃肿
2. 新增、删除子类均会违反开闭原则
三、简单工厂模式违反了开闭原则
还是上面的鼠标工厂,现在有了新需求,除了DellMouse和HpMouse,我们还需要LenovoMouse,那就需要对现有代码做些调整。
1. 首先新增LenovoMouse的实现类,实现Mouse接口:
public class LenovoMouse implements Mouse {@Overridepublic void sayHi() {System.out.println("我是联想鼠标");}
}
仅新增联想鼠标的做法,是符合开闭原则的,毕竟我们只扩展出了一个LenovoMouse的实现类,且没有修改当前代码。
2. 接下来需要修改工厂类MouseFactory,使其能够创建出LenovoMouse的实例
public class MouseFactory {public static Mouse createMouse(int type){switch (type){case 0 : return new DellMouse();case 1 : return new HpMouse();case 2 : return new LenovoMouse();default:return new DellMouse();}}public static void main(String[] args) {Mouse mouse = MouseFactory.createMouse(2);mouse.sayHi();}
}
在工厂中,我们在 switch 语句中添加了一条case, 为了能够让工厂返回LenovoMouse实例。
此时,因为修改了原有工厂类的方法,就违背了开闭原则。
四、建议
所有原则并非一定要严格遵守,而是需要结合业务的实际情况。
上面的例子中,如果我们只需要创建这几个Mouse的实现类,使用简单工厂,违背一下开闭原则也不是不可以。
更多推荐
简单工厂模式的实现及优缺点
发布评论