抽象工厂模式和工厂模式的区别? - 贾不假的回答 - 知乎 https://www.zhihu.com/question/20367734/answer/1089721250
简单工厂模式
引入
比如设计一个场景:博客系统的文章想要分为两类,一类是生活文章,一类是工作文章。
使用简单工厂模式去实现这个场景:
1. 两个文章类共同的父接口:ContentCenter (产品)
2. 两个文章类具体实现 (具体产品)
3. 文章工厂,通过传入的type,返回对应的文章实列。(工厂)
以上就凑齐了简单工厂的三个要素 产品、具体产品、工厂。
// 产品
public interface ContentCenter {
String getContent(int aid);
}
// 具体产品
public class DayPartImp implements ContentCenter {
@Override
public String getContent(int aid) {
String str = "生活文章:我爱妹妹";
return str;
}
}
public class WorkPartImp implements ContentCenter{
@Override
public String getContent(int aid) {
String str = "work文章:划水一天天";
return str;
}
}
// 工厂
public class ContentFactroy {
public ContentCenter getContentPart(int type,int aid) throws Exception{
if(type == 1){
return new WorkPartImp();
}else{
return new DayPartImp();
}
}
}
简单工厂模式适用于复杂对象的创建,用户只需要通过工厂得到对象,加以使用就行了,不用去管对象是怎么创建的。
问题
如果现在需要新加一类文章,那么就需要去修改工厂中的ifelse了,违反了开闭原则。
工厂方法模式
接着上面的例子,如果使用工厂方法来实现,那应该是这样的:
四部分: 工厂、具体工厂、产品、具体产品
// 产品
public interface ContentCenter {
String getContent(int aid);
}
// 具体产品
public class DayPartImp implements ContentCenter {
@Override
public String getContent(int aid) {
String str = "生活文章:我爱妹妹";
return str;
}
}
public class WorkPartImp implements ContentCenter{
@Override
public String getContent(int aid) {
String str = "work文章:划水一天天";
return str;
}
}
// 工厂
public interface ContentFactoryBig {
ContentCenter createContent();
}
// 具体工厂
class WorkFactory implements ContentFactoryBig{
@Override
public ContentCenter createContent() {
return new WorkPartImp();
}
}
class DayFactroy implements ContentFactoryBig{
@Override
public ContentCenter createContent() {
return new DayPartImp();
}
}
也就是说,每一种产品对象的创建,都对应这一个具体的工厂去创建,缺点是类会创建得比较多,优点是符合开闭原则,要是有新加的产品,只需要新加一个具体工厂就行。于简单工厂同样的,屏蔽了对象的创建过程。
抽象工厂模式
上面的工厂方法虽然看起来挺牛逼,但是其核心:每个工厂只能创建一种产品。 那么如果产品比较多,就会出现很多很多工厂类的情况。
为了避免这个问题呢,抽象工厂模式就出来啦!它把有关联的一类产品看成一个“产品族”,使用同一个工厂来创建。
比如咱引入一个列子:
KFC有现在需要同时卖鸡腿和可乐,但是不管是鸡腿和可乐都会有两个步骤,1.生产 2.卖(也可以看做是生产两种产品哦),那么咱需要准备的有:
1、 KFCFactory KFC工厂接口 (抽象工厂)
2、可乐工厂和鸡腿工厂 (具体工厂)
3、生产步骤,卖的步骤 (抽象产品)
4、 生产可乐、卖出可乐。 生产鸡腿、卖出鸡腿。 (具体产品)
// 抽象工厂
public interface KFCFactory {
PrepareThing createPrepareThingForSale();
SaleThing createSale();
}
// 具体工厂
public class JituiFactory implements KFCFactory {
@Override
public PrepareThing createPrepareThingForSale() {
return new JituiPrepareThing();
}
@Override
public SaleThing createSale() {
return new JituiSale();
}
}
public class CeleFactory implements KFCFactory {
@Override
public PrepareThing createPrepareThingForSale() {
return new KelePrepareThing();
}
@Override
public SaleThing createSale() {
return new keleSale();
}
}
// 抽象产品
public interface SaleThing {
void saySaleWhich();
}
public interface PrepareThing {
void sayPrepare();
}
// 具体产品
public class JituiSale implements SaleThing {
@Override
public void saySaleWhich() {
System.out.println("卖鸡腿拉");
}
}
public class keleSale implements SaleThing {
@Override
public void saySaleWhich() {
System.out.println("卖可乐,卖可乐");
}
}
public class KelePrepareThing implements PrepareThing {
@Override
public void sayPrepare() {
System.out.println("准备可乐呜呼呼");
}
}
public class JituiPrepareThing implements PrepareThing {
@Override
public void sayPrepare() {
System.out.println("鸡腿正在准备拉");
}
}
(对不起。。。例子举得不好,全想着KFC去了,还是网上那个WINDOWS和MAC 鼠标键盘的例子好理解)
产品族之间需要有逻辑或者约束,毕竟是要一起用的。
在抽象工厂模式中,增加新的产品族很方便,但是增加新的产品等级结构很麻烦。也就是说对产品族不会改变的系统,是符合开闭原则的。