工厂模式
简单工厂模式
程序猿最擅长的就是new一个对象,比如没有女朋友就自己new一个。但是new一个对象不是那么容易的,有许多问题需要我们去考虑。比如我们要根据不同条件去new不同的对象:
Girl girl = null;
if(I like fat girl){
girl = new FatGirl();
}else if(I like thin girl){
girl = new ThinGirl();
}
上面代码人人都会写,但是存在一些问题:
- 以后有其他新条件或其他新的Girl子类了,我们又得修改这段代码,违背了开闭原则
- 我并不太想知道new一个女孩的具体过程,我希望告诉你我想要是什么样的,直接给我结果就好
于是我们将new对象的代码封装起来,对调用者隐藏细节:
public class Factory {
public Girl createGirl(String whatYouLike){
Girl girl = null;
if(whatYouLike == "fat"){
girl = new FatGirl();
}else if(whatYouLike == "thin"){
girl = new ThinGirl();
}
return girl;
}
}
Girl类的具体代码就不写了,看下面类图就明白了。
这下程序员开心了,想要什么样的女孩一键搞定:
Girl girl = (new GirlFactory()).createGirl("fat");
没错,上面这短短几行代码就是简单工厂模式了。其类图如下:
不过我们有时候不会直接调用Factory,而会借助另外一个类使用组合的方式来调用Factory,这样的好处在于可以方便地选择用哪种工厂(假如有多个工厂可以选择):
借助的那个类可以叫做工厂提供者,代码如下:
public class GirlStore {
GirlFactory factory;
/**
* 可以动态选择工厂
* @param factory
*/
public GirlStore(GirlFactory factory){
this.factory = factory;
}
public Girl createGirl(String whatYouLike){
return factory.createGirl(whatYouLike);
}
}
调用的时候调用GirlStore而不是Factory:
GirlStore store = new GirlStore(new GirlFactory());
store.createGirl("thin");
有人说增加了 GirlStore
类更麻烦了。增加GirlStore
类的目的是为了扩展性,如果你很确定你的这块业务将来基本不怎么扩展,那么请你怎么简单怎么来,直接使用Factory类就好了,甚至直接new对象就好了。
设计模式是为了解决问题而诞生的,不是为了增加代码复杂性而诞生的。不要为了使用设计模式而使用设计模式。
综上,工厂模式简单来说就是将new对象的过程给封装起来了,调用者无需关注。但是前面说的两个问题目前只解决了第二个,如果我们要增加条件和Girl的子类时,还得修改工厂类。但抽象工厂模式不存在这个问题。
抽象工厂模式
判断你的代码是否遵循了“开闭原则”的一个很重要的指标是:
当你想要扩展功能的时候,是否需要修改已有代码?
如果不需要,那么恭喜你写的一手优雅的好代码。
抽象工厂模式是在简单工厂的基础上将未来可能需要修改的代码抽象出来,通过继承的方式让子类去做决定。
假如某某程序猿现在不满足于选择girl的胖瘦,他的口味有点特殊,喜欢美国产的长发姑娘,遵循开闭原则,我们需要使用抽象工厂,类图如下:
在抽象工厂中,我们将工厂抽象出来,由具体的子类工厂来决定生产什么样的对象。ChineseGirlFactory和AmericanGirlFactory分别生产不同种类的girl。girl是产品,而同一个工厂生产出来的girl我们称之为同一个产品族。
具体代码如下:
抽象工厂:
public abstract class AbstractGirlFactory {
/**
*
* @param whatYouLike 高矮胖瘦等类型
* @return
*/
public abstract Girl createGirl(String whatYouLike);
}
美国工厂:
public class AmericanGirlFactory extends AbstractGirlFactory{
@Override
public Girl createGirl(String whatYouLike) {
Girl girl = null;
if(whatYouLike == "fat"){
girl = new FatGirl();
}else if(whatYouLike == "thin"){
girl = new ThinGirl();
}
return girl;
}
}
中国工厂:
public class ChineseGirlFactory extends AbstractGirlFactory{
@Override
public Girl createGirl(String whatYouLike) {
Girl girl = null;
if(whatYouLike.equals("longhair")){
//girl = new LongHairGirl();
}
return girl;
}
}
工厂提供者:
public class GirlStore {
AbstractGirlFactory factory;
/**
* 可以动态选择工厂
* @param factory
*/
public GirlStore(AbstractGirlFactory factory){
this.factory = factory;
}
public Girl createGirl(String whatYouLike){
return factory.createGirl(whatYouLike);
}
//也可以返回工厂,让客户端自己去createGirl()
//public abstract AbstractGirlFactory createFactory(String country);
}
客户端调用:
GirlStore store = new GirlStore(new AmericanGirlFactory());
Girl girl = store.createGirl("longhair");
在这里中国工厂和美国工厂都是用于创建Girl,其实也可以分别创建不同的产品,一个创建Girl,另一个用于创建Computer等。设计模式是灵活的,不同场景下,具体的使用方式也会有所差别。
上面就是抽象工厂模式了。大家思考一下,如果以后还需要增加新的Girl类型,Girl对象,我们是不是只需要增加工厂类就行了,而不用修改原有的工厂类里的代码。
转载:https://gitbook.cn/gitchat/column/5b1e3647294fb04d7c22b783/topic/5b1fa54952823b71110333bc