zoukankan      html  css  js  c++  java
  • 简单工厂,工厂方法,抽象工厂模式对比

    概述

    三种模式都是针对创建对象的设计模式,其抽象层次约来越高,越来越遵循开闭原则,本着用扩展来支持修改的方式的方式和方法,采用空间换时间的方案。

    简单工厂

    先看段代码

    public static void main(String[] args)(
    BmwCar car =new BmwCar();
    car.push()
    )
    

    这是我们创建对象并使用的第一种使用方法
    这样创建的对象非常固定,没次需求变更都需要修改创建类。

    我们可以把创建对象的动作委托给第三方,把场景类和创建类的动作隔离开,只负责场景的逻辑,创建的逻辑我们不管,符合单一职责思想。

    //抽象产品  
    abstract class Car{  
        private String name;  
          
        public abstract void drive();  
          
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
    }  
    //具体产品  
    class Benz extends Car{  
        public void drive(){  
            System.out.println(this.getName()+"----go-----------------------");  
        }  
    }  
      
    class Bmw extends Car{  
        public void drive(){  
            System.out.println(this.getName()+"----go-----------------------");  
        }  
    }  
      
    //简单工厂  
    class Driver{  
        public static Car createCar(String car){  
            Car c = null;  
            if("Benz".equalsIgnoreCase(car))  
                c = new Benz();  
            else if("Bmw".equalsIgnoreCase(car))  
                c = new Bmw();  
            return c;  
        }  
    }  
      
    //老板  
    public class BossSimplyFactory {  
      
        public static void main(String[] args) throws IOException {  
            //老板告诉司机我今天坐奔驰  
            Car car = Driver.createCar("benz");  
            car.setName("benz");  
             //司机开着奔驰出发  
            car.drive();  
        }  
    }
    

    以上结构就把创建car的动作交给Driver类实现,场景类只负责发号时令就行。这就是简单工厂模式为我们做的事情。

    工厂方法模式

    可是简单工厂模式有个确定,没次增加新车都需要修改Driver类,这样我们就把Driver做成抽象类或者接口,这样没次增加新产品只要增加一个对应的Driver实现类就行了。代码如下:

    //抽象产品  
    abstract class Car{  
        private String name;  
          
        public abstract void drive();  
          
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
    }  
    //具体产品  
    class Benz extends Car{  
        public void drive(){  
            System.out.println(this.getName()+"----go-----------------------");  
        }  
    }  
    class Bmw extends Car{  
        public void drive(){  
            System.out.println(this.getName()+"----go-----------------------");  
        }  
    }  
      
      
    //抽象工厂  
    abstract class Driver{  
        public abstract Car createCar(String car) throws Exception;  
    }  
    //具体工厂(每个具体工厂负责一个具体产品)  
    class BenzDriver extends Driver{  
        public Car createCar(String car) throws Exception {  
            return new Benz();  
        }  
    }  
    class BmwDriver extends Driver{  
        public Car createCar(String car) throws Exception {  
            return new Bmw();  
        }  
    }  
      
    //老板  
    public class Boss{  
      
        public static void main(String[] args) throws Exception {  
            Driver d = new BenzDriver();  
            Car c = d.createCar("benz");   
            c.setName("benz");  
            c.drive();  
        }  
    }
    

    比简单工厂更具抽象性,工厂类和产品类都是抽象类或者接口。这样的方法只支持产品树逻辑的创建需求,如果有产品族类的需求该怎么办呢?
    什么是产品族?产品族就是不同产品树的横向产品分类,就是说产品有横向和纵向两个纬度区分的时候需要用到抽象工厂模式

    抽象工厂模式

    先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。

    图中的BmwCar和BenzCar就是两个产品树(产品层次结构);而如图所示的BenzSportsCar和BmwSportsCar就是一个产品族。他们都可以放到跑车家族中,因此功能有所关联。同理BmwBussinessCar和BenzBusinessCar也是一个产品族。

    可以这么说,它和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。

    而且使用抽象工厂模式还要满足一下条件:

    1.系统中有多个产品族,而系统一次只可能消费其中一族产品

    2.同属于同一个产品族的产品以其使用。

    来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):

    抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。

    具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。

    抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。

    具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。

    //抽象产品(Bmw和Audi同理)  
    abstract class BenzCar{  
        private String name;  
          
        public abstract void drive();  
          
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
    }  
    //具体产品(Bmw和Audi同理)  
    class BenzSportCar extends BenzCar{  
        public void drive(){  
            System.out.println(this.getName()+"----BenzSportCar-----------------------");  
        }  
    }  
    class BenzBusinessCar extends BenzCar{  
        public void drive(){  
            System.out.println(this.getName()+"----BenzBusinessCar-----------------------");  
        }  
    }  
      
    abstract class BmwCar{  
        private String name;  
          
        public abstract void drive();  
          
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
    }  
    class BmwSportCar extends BmwCar{  
        public void drive(){  
            System.out.println(this.getName()+"----BmwSportCar-----------------------");  
        }  
    }  
    class BmwBusinessCar extends BmwCar{  
        public void drive(){  
            System.out.println(this.getName()+"----BmwBusinessCar-----------------------");  
        }  
    }  
      
    abstract class AudiCar{  
        private String name;  
          
        public abstract void drive();  
          
        public String getName() {  
            return name;  
        }  
        public void setName(String name) {  
            this.name = name;  
        }  
    }  
    class AudiSportCar extends AudiCar{  
        public void drive(){  
            System.out.println(this.getName()+"----AudiSportCar-----------------------");  
        }  
    }  
    class AudiBusinessCar extends AudiCar{  
        public void drive(){  
            System.out.println(this.getName()+"----AudiBusinessCar-----------------------");  
        }  
    }  
      
      
    //抽象工厂  
    abstract class Driver3{  
        public abstract BenzCar createBenzCar(String car) throws Exception;  
          
        public abstract BmwCar createBmwCar(String car) throws Exception;  
          
        public abstract AudiCar createAudiCar(String car) throws Exception;  
    }  
    //具体工厂  
    class SportDriver extends Driver3{  
        public BenzCar createBenzCar(String car) throws Exception {  
            return new BenzSportCar();  
        }  
        public BmwCar createBmwCar(String car) throws Exception {  
            return new BmwSportCar();  
        }  
        public AudiCar createAudiCar(String car) throws Exception {  
            return new AudiSportCar();  
        }  
    }  
    class BusinessDriver extends Driver3{  
        public BenzCar createBenzCar(String car) throws Exception {  
            return new BenzBusinessCar();  
        }  
        public BmwCar createBmwCar(String car) throws Exception {  
            return new BmwBusinessCar();  
        }  
        public AudiCar createAudiCar(String car) throws Exception {  
            return new AudiBusinessCar();  
        }  
    }  
      
    //老板  
    public class BossAbstractFactory {  
      
        public static void main(String[] args) throws Exception {  
              
            Driver3 d = new BusinessDriver();  
            AudiCar car = d.createAudiCar("");  
            car.drive();  
        }  
    }  
    

    其中:BenzSportCar和BenzBusinessCar属于产品树;同理BmwSportCar和BmwBusinessCar。而BenzSportCar和BmwSportCar和AudiSportCar属于产品族。
    所以抽象工厂模式一般用于具有产品树和产品族的场景下。

    抽象工厂模式的缺点:如果需要增加新的产品树,那么就要新增三个产品类,比如VolvoCar,VolvoSportCar,VolvoSportCar,并且要修改三个工厂类。这样大批量的改动是很丑陋的做法。

    所以可以用简单工厂配合反射来改进抽象工厂:

    UML图略。

    abstract class BenzCar{
    private String name;
    
    public abstract void drive();
    
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    }
    class BenzSportCar extends BenzCar{
    public void drive(){
    System.out.println(this.getName()+"----BenzSportCar-----------------------");
    }
    }
    class BenzBusinessCar extends BenzCar{
    public void drive(){
    System.out.println(this.getName()+"----BenzBusinessCar-----------------------");
    }
    }
    
    abstract class BmwCar{
    private String name;
    
    public abstract void drive();
    
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    }
    class BmwSportCar extends BmwCar{
    public void drive(){
    System.out.println(this.getName()+"----BmwSportCar-----------------------");
    }
    }
    class BmwBusinessCar extends BmwCar{
    public void drive(){
    System.out.println(this.getName()+"----BmwBusinessCar-----------------------");
    }
    }
    
    abstract class AudiCar{
    private String name;
    
    public abstract void drive();
    
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    }
    class AudiSportCar extends AudiCar{
    public void drive(){
    System.out.println(this.getName()+"----AudiSportCar-----------------------");
    }
    }
    class AudiBusinessCar extends AudiCar{
    public void drive(){
    System.out.println(this.getName()+"----AudiBusinessCar-----------------------");
    }
    }
    
    
    /**
    * 简单工厂通过反射改进抽象工厂及其子工厂
    * @author Administrator
    *
    */
    class Driver3{
    public static BenzCar createBenzCar(String car) throws Exception {
    return (BenzCar) Class.forName(car).newInstance();
    }
    
    public static BmwCar createBmwCar(String car) throws Exception {
    return (BmwCar) Class.forName(car).newInstance();
    }
    
    public static AudiCar createAudiCar(String car) throws Exception {
    return (AudiCar) Class.forName(car).newInstance();
    }
    }
    //客户端
    public class SimpleAndAbstractFactory {
    
    public static void main(String[] args) throws Exception {
    
    AudiCar car = Driver3.createAudiCar("com.java.pattendesign.factory.AudiSportCar");
    car.drive();
    }
    }
    
    定位问题原因* 根据原因思考问题解决方案* 实践验证方案有效性* 提交验证结果
  • 相关阅读:
    资深项目经理推荐的几款免费/开源项目管理工具
    内网穿透工具frp简单使用教程
    10部全尺度欧美宫斗剧!献给不甘平淡的你
    Spring Boot后端+Vue前端+微信小程序,完整的开源解决方案!
    搭建Keepalived + Nginx + Tomcat的高可用负载均衡架构
    集成Activiti工作流的J2EE快速开发框架
    国内5大前端团队网站,你了解多少
    5 天 4000 star 的一个爆款开源项目
    「干货」常用的10个网络DOS命令,菜鸟学了变高手
    js自定义正则表达式
  • 原文地址:https://www.cnblogs.com/jimoliunian/p/14602451.html
Copyright © 2011-2022 走看看