创建型模式:抽象工厂模式(Abstract Factory)--分析优缺点

本文深入探讨了抽象工厂模式在麦当劳和肯德基B套餐应用中的作用,解释了如何通过抽象工厂模式简化客户选择套餐的过程,以及其在软件设计中的优点和缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载地址:http://blog.youkuaiyun.com/lingyun_blog/article/details/41479563


追MM少不了请吃饭了,麦当劳的套餐和肯德基的套餐都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“两个B套餐”就行了。麦当劳和肯德基就是B套餐的Abstract Factory, B套餐里含有汉堡, 鸡翅和饮料. 麦当劳或肯德基会根据B套餐的规格, 让汉堡Factory, 鸡翅Factory, 饮料Factory分别生产对应B套餐的材料.


定义  
        有称作“工具箱”模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。



使用场景

        一个系列要独立于它的产品的创建、组合和表示时。
        一个系统要由多个产品系列中的一个来配置时。
        当要强调一系列相关的产品对象的设计以便进行联合使用时。
        当要提供一个产品类库,而只要显示它们的接口而不是实现时。
        简单的说就是适用于客户端中经常需要切换配置(交换产品系列)时,客户端通过抽象接口来操纵实例,具体的类名不会出现在客户端中。



优缺点分析

     优点    缺点
简单工厂模式    
分离了客户端和后台逻辑,使得客户端无需关心后台的实现,去除了客户端与具体产品的依赖,增强了移植性能。
实现简单,易于操作。
违背了开放-封闭原则
添加新产品时比较麻烦
工厂方法模式    
是简单工厂模式的升级
易于添加新产品
后台模块契合了开放-封闭原则
新产品的添加带来了大量新的类的创建,增加了工作量
客户端部分仍然违反开放-封闭原则,只是后台判断逻辑挪到了前台
抽象工厂模式    
分离了具体的类,工厂封装了创建产品对象的责任和过程,将客户端和类的实现分离,客户端通过抽象接口操纵实例
易于交换产品系列,一个具体的工厂类在一个应用中仅在初始化时出现一次,改变一个应用的具体工厂变得容易
有利于产品的一致性,一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一系列中的对象
难以支持新种类的产品,抽象工厂接口确定了可以被创建的产品集合。新种类产品加入需要扩展抽象工厂接口,这就涉及到了接口本身和所有实现类的改变



角色及其职责
抽象工厂(Abstract Factory)角色:担任这个角色的是工厂方法模式的核心,它是与应用系统商业逻辑无关的。
具体工厂(Concrete Factory)角色:这个角色直接在客户端的调用下创建产品的实例。这个角色含有选择合适的产品对象的逻辑,而这个逻辑是与应用系统的商业逻辑紧密相关的。
抽象产品(Abstract Product)角色:担任这个角色的类是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
具体产品(Concrete Product)角色:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。这是客户端最终需要的东西,其内部一定充满了应用系统的商业逻辑。



抽象工厂模式UML图


应用场景及代码分析
       程序员小明使用工厂方法模式对面包店进行了一番改造,效果显著,加入新的面包时变得容易了,可是,小明的生意做的越来越大,并不满足只卖面包了,他想在自己的店里面加入自己喜欢吃的披萨,于是按照他开始了编码的道路
       首先将我们的面包师和面包写出来:
[java] view plaincopy
//面包师,作为父类  
public class BreadMaker {  
    //生产面包  
    public  void getBread(){  
        //等待孩子们生产出来  
    }  
}  
 
//奶油面包  
public class ButterBread extends BreadMaker{  
    // 覆盖父类方法  
    @Override  
    public void getBread() {  
        // TODO Auto-generated method stub  
        super.getBread();  
        System.out.println("烤出了奶油面包");  
    }  
}  
 
//巧克力面包  
public class ChocolateBread extends BreadMaker{  
    // 覆盖父类方法  
    @Override  
    public void getBread() {  
        // TODO Auto-generated method stub  
        super.getBread();  
        System.out.println("烤出了巧克力面包");  
    }  
}  
 
//香蕉面包  
public class BananaBread extends BreadMaker{  
    // 覆盖父类方法  
    @Override  
    public void getBread() {  
        // TODO Auto-generated method stub  
        super.getBread();  
        System.out.println("烤出了香蕉面包");  
    }  
}  



同样,类似于面包师和面包,也创建出了披萨师和各种披萨
[java] view plaincopy
//披萨师 各种披萨的父类  
public class PizzaMaker {  
    //制作披萨  
    public void GetPizza(){  
          
    }  
}  
 
//奶油披萨  
public class ButterPizza extends PizzaMaker {  
 
    @Override  
    public void GetPizza() {  
        // TODO Auto-generated method stub  
        super.GetPizza();  
        System.out.println("制作出了奶油披萨");  
    }  
}  
 
//巧克力披萨  
public class ChocolatePizza extends PizzaMaker {  
 
    @Override  
    public void GetPizza() {  
        // TODO Auto-generated method stub  
        super.GetPizza();  
        System.out.println("制作出了巧克力披萨");  
    }  
}  
 
//香蕉披萨  
public class BananaPizza extends PizzaMaker {  
 
    @Override  
    public void GetPizza() {  
        // TODO Auto-generated method stub  
        super.GetPizza();  
        System.out.println("制作出了香蕉披萨");  
    }  
}  


写到这里,按照之前工厂方法模式的方法,还需要添加新的工厂接口和3个披萨实体类对应的工厂实体类,小明突然发现这样做的成本太大了,回头想了想,原来披萨和面包的制作方法都是相似的嘛,完全可以放在一起制作啊,对于顾客来说,他们并不关心面包和披萨在哪里做出来的,关心的是面包和披萨的直接、快速取得。于是在同一个工厂里加入了披萨工厂。
[java] view plaincopy
//工厂接口  
public interface IFactory {  
    BreadMaker createBread();  
    //增加了返回披萨实例的接口方法  
    PizzaMaker createPizzer();  
}  
 
//奶油面包和奶油披萨的工厂方法实现  
public class ButterBreadFactory implements IFactory{  
 
    @Override  
    public BreadMaker createBread() {  
        //返回奶油面包实例  
        return new ButterBread();  
    }  
 
    @Override  
    public PizzaMaker createPizzer() {  
        // 返回奶油披萨实例  
        return new ButterPizza();  
    }  
}  
 
//巧克力面包和巧克力披萨的工厂方法实现  
public class ChocolateBreadFactory implements IFactory{  
    @Override  
    public BreadMaker createBread() {  
        //返回巧克力面包实例  
        return new ButterBread();  
    }  
 
    @Override  
    public PizzaMaker createPizzer() {  
        // 返回巧克力披萨实例  
        return null;  
    }  
}  
 
 
//香蕉面包和香蕉披萨的工厂方法实现  
public class BananaBreadFactory implements IFactory{  
    @Override  
    public BreadMaker createBread() {  
        //返回香蕉面包实例  
        return new ButterBread();  
    }  
 
    @Override  
    public PizzaMaker createPizzer() {  
        //返回香蕉披萨实例  
        return null;  
    }  
}  


现在小明又开始重新开张了:
[java] view plaincopy
//抽象工厂模式测试  
public class AbstractFactoryTest {  
 
    public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        System.out.println("小明面包披萨店开始营业!");  
        BreadMaker breadMaker = null;  
        PizzaMaker pizzaMaker = null;  
        IFactory breadFactory = null;  
        System.out.println("顾客要一个奶油面包");  
        //根据需要实例化接口  
        breadFactory = new ButterBreadFactory();  
        breadMaker =breadFactory.createBread();  
        breadMaker.getBread();  
          
        System.out.println("顾客要一个奶油披萨");  
        pizzaMaker =breadFactory.createPizzer();  
        pizzaMaker.GetPizza();  
    }  
}  


输出结果:
小明面包披萨店开始营业!
顾客要一个奶油面包
烤出了奶油面包
顾客要一个奶油披萨
制作出了奶油披萨


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值