持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情
回顾工厂方法模式
上篇文章介绍的是工厂方法模式,它的UML类图是这样的
工厂方法模式中的例子是计算器,加减乘除四个工厂类都必须实现FactoryMethod这个向上抽取的接口,并根据自己的产品(加法工厂new的加法对象,减法工厂new的是减法对象,乘法对象new的是......)重写接口中的createOperation()方法。这四个工厂虽然可以产生不同的运算对象,但是他们都有一个共同的爹,那就是Operation。这时候就会出现问题,往下看。
听个故事
话说莆田有一个富豪叫老林,老林手底下有一个大工厂,工厂里有三个主要的业务,分别是鞋,珠宝,实木家具。随着自己慢慢变老,老林打算把工厂三个业务交给三个儿子来打理。可是他遇到了一个难题,目前鞋子生意备受打压,生意不景气,把鞋分给那个儿子来做都不公平。
经过一番思考后,老林想到了较为公平的做法,已知鞋,珠宝,实木家具都有三种风格,分别是中国风,欧美风,日韩风。让三个儿子分别继承一种风格就可以了,这样三个儿子都可以做鞋,珠宝,实木家具,只不过是风格不同。最终老林决定大儿子继承中国风,二儿子继承欧美风,三儿子继承日韩风。
分析一波
想实现这个案例,如果使用工厂方法模式是否可行呢?答案是不行的,因为工厂方法模式只能生产一种产品,要么生产鞋,要么生产珠宝,要么生产实木家具。同时生产三个产品是工厂方法所不具备的。所以前辈们在工厂方法模式的基础上,总结出了抽象工厂模式。
抽象工厂模式是工厂方法模式的一种延伸,在工厂方法模式中,我们的顶层接口FactoryMethod中只有一个创建对象方法createOperation(),而在抽象工厂中,需要有三个创建不同对象的方法,在老林工厂的案例中,我们就需要创建鞋对象,珠宝对象,实木对象这三个方法。
实现一下
UMl类图
工厂类
抽象工厂:抽象出来的顶层接口
public interface AbstractFactory {
Gem createGem();
Shoes createShoes();
Wood createWood();
}
中国风工厂:实现抽象工厂
public class ChineseStyleFactory implements AbstractFactory {
@Override
public Gem createGem() {
return new ChineseStyleGem();
}
@Override
public Shoes createShoes() {
return new ChineseStyleShoes();
}
@Override
public Wood createWood() {
return new ChineseStyleWood();
}
}
欧美风工厂:实现抽象工厂
public class EuropeanStyleFactory implements AbstractFactory {
@Override
public Gem createGem() {
return new EuropeanStyleGem();
}
@Override
public Shoes createShoes() {
return new EuropeanStyleShoes();
}
@Override
public Wood createWood() {
return new EuropeanStyleWood();
}
}
日韩风工厂:实现抽象工厂
public class JapaneseKoreanStyleFactory implements AbstractFactory {
@Override
public Gem createGem() {
return new JapaneseKoreanStyleGem();
}
@Override
public Shoes createShoes() {
return new JapaneseKoreanStyleShoes();
}
@Override
public Wood createWood() {
return new JapaneseKoreanStyleWood();
}
}
产品类
鞋:三个风格子类分别实现鞋接口
public interface Shoes {
void shoesProduct();
}
// 中国风鞋
public class ChineseStyleShoes implements Shoes {
@Override
public void shoesProduct() {
System.out.println("这是中国风鞋子!");
}
}
// 欧美风鞋
public class EuropeanStyleShoes implements Shoes {
@Override
public void shoesProduct() {
System.out.println("这是欧美风鞋子!");
}
}
// 日韩风鞋
public class JapaneseKoreanStyleShoes implements Shoes {
@Override
public void shoesProduct() {
System.out.println("这是日韩风鞋子!");
}
}
珠宝 :三个风格子类分别实现珠宝接口
public interface Gem {
void gemProduct();
}
// 中国风珠宝
public class ChineseStyleGem implements Gem {
@Override
public void gemProduct() {
System.out.println("这是中国风珠宝!");
}
}
// 欧美风珠宝
public class EuropeanStyleGem implements Gem {
@Override
public void gemProduct() {
System.out.println("这是欧美风珠宝!");
}
}
// 日韩风珠宝
public class JapaneseKoreanStyleGem implements Gem{
@Override
public void gemProduct() {
System.out.println("这是日韩风珠宝!");
}
}
实木家具:三个风格子类分别实现实木家具接口
public interface Wood {
void woodProduct();
}
// 中国风实木家具
public class ChineseStyleWood implements Wood {
@Override
public void woodProduct() {
System.out.println("这是中国风实木家具!");
}
}
// 欧美风实木家具
public class EuropeanStyleWood implements Wood {
@Override
public void woodProduct() {
System.out.println("这是欧美风实木家具!");
}
}
// 日韩风实木家具
public class JapaneseKoreanStyleWood implements Wood{
@Override
public void woodProduct() {
System.out.println("这是日韩风实木家具!");
}
}
测试
测试代码
public class AbsTest {
public static void main(String[] args) {
AbstractFactory chineseFactory = new ChineseStyleFactory();
chineseFactory.createGem().gemProduct();
chineseFactory.createShoes().shoesProduct();
chineseFactory.createWood().woodProduct();
System.out.println("=========我是分割线=========");
AbstractFactory europeanFactory = new EuropeanStyleFactory();
europeanFactory.createGem().gemProduct();
europeanFactory.createShoes().shoesProduct();
europeanFactory.createWood().woodProduct();
System.out.println("=========我是分割线=========");
AbstractFactory japaneseKoreanFactory = new JapaneseKoreanStyleFactory();
japaneseKoreanFactory.createGem().gemProduct();
japaneseKoreanFactory.createShoes().shoesProduct();
japaneseKoreanFactory.createWood().woodProduct();
}
}
结果:
这是中国风珠宝!
这是中国风鞋子!
这是中国风实木家具!
=========我是分割线=========
这是欧美风珠宝!
这是欧美风鞋子!
这是欧美风实木家具!
=========我是分割线=========
这是日韩风珠宝!
这是日韩风鞋子!
这是日韩风实木家具!
总结
抽象工厂的UML类图虽然看起来很可怕,实际它就是模板方法的一种衍生,当你需要一个生产多个类型不同的产品时,你可以考虑下抽象工厂模式。每当我们新增一个产品时,只需要增加UML类图竖着的方框中的几个类即可,可以看到抽象工厂模式的可扩展性是非常好的。