让代码变美的第三天 - 简单工厂模式
丑陋的模样
public void sendApple() {
Apple apple = new Apple();
// 洗苹果 + 切苹果
apple.wash();
apple.cut();
// 使用苹果:苹果送人
sendPeople(apple);
}
public void eatApple() {
Apple apple = new Apple();
// 洗苹果 + 切苹果
apple.wash();
apple.cut();
// 使用苹果:吃苹果
eatPeople(apple);
}
public void eatPineapple() {
Pineapple apple = new Pineapple();
// 洗菠萝 + 切菠萝
apple.cut();
// 使用菠萝:吃菠萝
eat(apple);
}
- 上面代码,两次使用苹果代码有部分重叠,代码冗余。
- 虽然新增一种水果(荔枝)不会破坏开闭原则,但是代码过于分散,不便于管理、维护。
变美步骤
第一步 - 基本预期
思考:这种产品(苹果、菠萝)在使用上会不会很多(比如上面苹果使用了2次,菠萝使用了一次)?这类产品将来会不会新增?,比如:香蕉、荔枝…
如果使用的地方很多,而且将来还会不断新增,那么重构一下还是比较好的。
第二步 - 梳理核心逻辑
使用这类产品的时候是不是总是需要创建、初始化。比如;一个产品初始化的东西基本固定,比如苹果一定要先洗,再切,然后再能端出来卖。
第三步 - 重构
给这个产品抽象出一个父类,比如水果
public interface Fruit {
}
public class Apple implements Fruit {
public void eat() {
System.out.println("吃苹果");
}
}
public class Pineapple implements Fruit {
public void eat() {
System.out.println("吃菠萝");
}
}
定义产品工厂,把每个产品的定义+初始化的动作都完成之后,形成一个可使用的产品再交出去
public static Fruit getFruit(String name) {
if ("苹果".equals(name)) {
Apple apple = new Apple();
// 洗苹果 + 切苹果
// todo other init
return apple;
} else if ("菠萝".equals(name)) {
Pineapple pineapple = new Pineapple();
// 切菠萝
// todo other init
return pineapple;
} else {
throw new RuntimeException("没有找到该水果");
}
}
- 将来新增初始化动作,或者想把菠萝换成“黑凤梨”也不用到处去改之前使用的地方
使用
public void sendApple() {
Fruit apple = FruitFacory.getFruit("苹果");
sendPeople(apple);
}
public void eatApple() {
Fruit apple = FruitFacory.getFruit("苹果");
eatPeople(apple);
}
public void eatPineapple() {
Fruit pineapple = FruitFacory.getFruit("菠萝");
eat(apple);
}
- 使用的时候不用管初始化动作了,直接拿来就是可以用的产品
破坏了开放封闭原则
确实是破坏了开放封闭原则,但是大多数业务代码中,我们新增一个产品的时候,大概率也需要改代码的,无非是改使用的地方,还是改工厂里面的【if else】,所以问题不大,但是这样改造之后,逻辑收敛,并且优化了重复的代码(初始化过程),对于管理维护来说还是比较划算的。
一般来说简单工厂是够用的,如果实在接受不了破坏了开闭原则,可以上【工厂方法模式】,但是它也有一些优缺点,如下:
优点:重复代码可以去掉,并且也满足开闭原则
缺点:代码变得很臃肿,未来新增产品的同时还会额外新增一个工厂,代码量变多了,同类产品没有一个地方进行统一管理(可读性、可维护性略差)