设计模式-抽像工厂

Posted bateman6988

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-抽像工厂相关的知识,希望对你有一定的参考价值。

 一。概念

  提供一个创建一系列相关或相互依赖对像的接口,而无需指定它们具体的类。

二。模式动机

  这一系列对像之间是相互依赖的,相当于一个产品族

 三。模式的结构

  

  通过上图我们可以清楚的看到抽像工厂模式包括以下4个角色:

  1.抽像工厂角色(AbstractFactory):抽像工厂模式的核心,与具体的商业逻辑无关,通常是一个JAVA接口或者抽像类。

  2.具体工厂角色(Concrete Factory):该角色通常与具体的商业逻辑紧密相关,该角色里面的工厂方法依据具体的商业逻辑实例化具体的产品并返回,客户端通过该角色并调用该角色的工厂方法,获得具体产品对像,该角色通常都是一个具体JAVA类来承担。

  3.抽像产品角色:担任这个角色的类是工厂方法模式所创建的产品的父类,或者他们共同拥有的接口,通常是一个接口或者抽像类。

  4.具体产品角色:抽像工厂模式所创建的任何产品都是这个角色的实例,有一个具体JAVA类来承担。

  样例代码如下:

   

public class AbstractProductA 
{
   
   /**
    * @roseuid 59AC05990327
    */
   public AbstractProductA() 
   {
    
   }
}


public class ProductA1 extends AbstractProductA 
{
   
   /**
    * @roseuid 59AC05990359
    */
   public ProductA1() 
   {
    
   }
}


public class ProductA2 extends AbstractProductA 
{
   
   /**
    * @roseuid 59AC05990381
    */
   public ProductA2() 
   {
    
   }
}

public class AbstractProductB 
{
   
   /**
    * @roseuid 59AC059903BA
    */
   public AbstractProductB() 
   {
    
   }
}

public class ProductB1 extends AbstractProductB 
{
   
   /**
    * @roseuid 59AC059A001F
    */
   public ProductB1() 
   {
    
   }
}

public class ProductB2 extends AbstractProductB 
{
   
   /**
    * @roseuid 59AC059A0049
    */
   public ProductB2() 
   {
    
   }
}



public abstract class AbstractFactory 
{
   
   /**
    * @roseuid 59AC05690005
    */
   public AbstractFactory() 
   {
    
   }
   
   /**
    * @return AbstractProductA
    * @roseuid 59ABFB0103BE
    */
   public  Abstract  AbstractProductA createProductA() ;
   
   
   /**
    * @return AbstractProductB
    * @roseuid 59ABFB3B029D
    */
   public Abstract AbstractProductB createProductB() ;
}


public class ConcreteFactory1 extends AbstractFactory 
{
   
   /**
    * @roseuid 59AC057A02FC
    */
   public ConcreteFactory1() 
   {
    
   }
   
   /**
    * @return AbstractProductA
    * @roseuid 59ABFB9C00C9
    */
   public AbstractProductA createProductA() 
   {
        return new ProductA1();
   }
   
   /**
    * @return AbstractProductB
    * @roseuid 59ABFBA30011
    */
   public AbstractProductB createProductB() 
   {
        return new ProductB1();
   }
}




public class ConcreteFactory2 extends AbstractFactory 
{
   
   /**
    * @roseuid 59AC057A02C0
    */
   public ConcreteFactory2() 
   {
    
   }
   
   /**
    * @return AbstractProductA
    * @roseuid 59ABFCC701B9
    */
   public AbstractProductA createProductA() 
   {
        return new ProductA2();
   }
   
   /**
    * @return AbstractProductB
    * @roseuid 59ABFCC9001F
    */
   public AbstractProductB createProductB() 
   {
        return new ProductB2();
   }
}

 

public class Client 
{
   
   
   /**
    * @roseuid 59AC055700AB
    */
   public Client() 
   {
    
   }

   public static void main(String[] args){
           AbstractFactory theAbstractFactory;
        AbstractProductA theAbstractProductA;
        AbstractProductB theAbstractProductB;

        theAbstractFactory=new ConcreteFactory1();

        theAbstractProductA=theAbstractFactory.createProductA();
        theAbstractProductB=theAbstractFactory.createProductB();
  
   }
}

   跟据上面的模式结构图我们对“提供一个创建一系列相关或相互依赖对像的接口,而无需指定它们具体的类”  进行一个简要的分析:

       1.相关相互依赖对像,在这里面ProductA1的实例和ProductB1的实例就是一组相互关联(如内在的关联关系)或相互依赖(如整体和部分)关系,依据业务逻辑,ProductA1

 只能和同一产品等级结构AbstractProductB下的ProductB1相互关联而无法与ProductB2关联在一起。

  2.提供一个创建一系列相关或相互依赖对像的接口,而无需指定它们具体的类,这里面的接口,即为结构图中的AbstractProductA和AbstractProductB,客户端只依赖这些产品的接口进行编程,而不依赖于具体实现,即符合依赖倒转原则。“无需指定它们具体的类”  即客户端(client)跟本就不知道ProductA1、ProductA2、ProductB1和ProductB2的存在,客户端只需要调用具体工厂的工厂方法即可返回具体的产品实例。

 

四。模式样例

  我们接着工厂方法模式中的样例进行进一步分析,现在这个生产轮胎的工厂已经不满足只生产轿车轮胎了,他现已经引入了发动机的生产线(EngineLine)、车门(DoorLine)等整个车的各种零部件生产线,可以说他现在可以轻松制造一部Car,但是也并非所有的Car都能制造,比如他现只能生产benz和BMW两种类型的车(这样的工厂也够NX了),比如现在一部车只包含车轮胎、车门和发动机(当然肯定不止这么多),那么这个工厂就可以跟据客户的要求生产BMW和benz车了,如下图:

 

  代码如下:

  

public interface Door {
    public void open();
    public void close();
}
public class BenzDoor implements Door {

    @Override
    public void open() {
        System.out.println("奔驰车门开");
    }

    @Override
    public void close() {
        System.out.println("奔驰车门关");
    }
}
public class BmwDoor implements Door {

    @Override
    public void open() {
        System.out.println("宝马车门开");
    }

    @Override
    public void close() {
        System.out.println("宝马车门关");
    }

}
public interface Tire {
    public void getColor();
    public void getLife();
    public void getWidth();
}
public class BenzTire implements Tire {

    @Override
    public void getColor() {
        System.out.println("benz车color");
    }

    @Override
    public void getLife() {
        System.out.println("benz车life");
    }

    @Override
    public void getWidth() {
        System.out.println("benz车width");
    }
}
public class BmwTire implements Tire {

    @Override
    public void getColor() {
        System.out.println("bmw车color");
    }

    @Override
    public void getLife() {
        System.out.println("bmw车life");
    }

    @Override
    public void getWidth() {
        System.out.println("bmw车width");
    }

}
public interface Engine {
    public void start();

    public void stop();

}
public class BenzEngine implements Engine {

    @Override
    public void start() {
        System.out.println("benz车start");

    }

    @Override
    public void stop() {
        System.out.println("benz车stop");

    }

}
public class BmwEngine implements Engine {

    @Override
    public void start() {
        System.out.println("bmw车start");

    }

    @Override
    public void stop() {
        System.out.println("bmw车stop");

    }

}
public interface PartFactory {
    public Door createDoor();

    public Tire createTire();

    public Engine createEngine();

}
public class BenzPartFactory implements PartFactory {

    @Override
    public Door createDoor() {
        return new BenzDoor();
    }

    @Override
    public Tire createTire() {
        return new BenzTire();
    }

    @Override
    public Engine createEngine() {
        return new BenzEngine();
    }

}
public class BmwPartFactory implements PartFactory {

    @Override
    public Door createDoor() {
        return new BmwDoor();
    }

    @Override
    public Tire createTire() {
        return new BmwTire();
    }

    @Override
    public Engine createEngine() {
        return new BmwEngine();
    }

}
public class Car {
    private Door door;
    private Engine engine;
    private Tire tire;

    public Car(PartFactory factory) {
        this.door = factory.createDoor();
        this.engine = factory.createEngine();
        this.tire = factory.createTire();
    }

    public Door getDoor() {
        return door;
    }

    public Engine getEngine() {
        return engine;
    }

    public Tire getTire() {
        return tire;
    }    
}
public class Client {
    
    public static void main(String[] args) {
        PartFactory partFactory=new BenzPartFactory();
        Car benzCar=new Car(partFactory);
        
        benzCar.getDoor().open();
        benzCar.getEngine().start();
        benzCar.getTire().getColor();
        
    }

}

  运行结果如下:

  奔驰车门开
  benz车start
  benz车color

      跟据上面的类图及运行结果可以做如下分析:

           BenzDoor、BenzTire和BenzEngine有很强的关联关系,我们可以说一部benz车,不可能用Bmw的车门,即BmwDoor。这种很强的关联关系通过BenzPartFactory进行了很好的维护。对于客户端来说,如上面的client类,如果客户想要一部benz车,那么我只需要一个生产benz车的工厂即可,这个工厂所有的产品实例,都是benz车的部件。从运行结果我们也可以看出。

         试想一下,随着这个工厂的发展,他现在也要生产Audi的车,这时我们只要增加一个audi的车门的类AudiDoor、AudiTire 、AudiEngine和AudiPartFactory就可以了,其它的类不需要做任何的修改。但客户说,我要在车上装一对翅膀呢,堵车时可以飞,这时我们就要对每个工厂都要增加能返回翅膀的工厂方法,要对每个工厂进行修改,这是不符合开闭原则的。所以说抽象工厂对增加产品等级结构方面是不支持开闭原则的,对于产品族维度(如audi车)是支持开闭原则的。

 

 五。模式的约束

  对于产生一个相互关联或依赖的产品族适用,且支持在产品族方向的扩展,不适用于产品等级方向的扩展。

六。模式的变体与扩展

  1、抽像工厂提供静态工厂方法:抽像工厂可以提供一个静态的工厂方法,通过参数返回具体的工厂实例。

  2、抽像工厂与具体工厂合并:如果在产品族方向上确定只有一个产品族,那么抽像工厂就没有必要了,这时只需要一个具体工厂就可以了,我们可以进一步延深,为这个具体工厂提供一个静态方法,该方法返回自已的实例。

七。与其它模式的关系

  如果只有一个产品等级结构,那么就是工厂方法模式了,如下图:

  

 

  如果有多个产品等级结构,那么抽像工厂里面的每一个工厂方法都是"工厂方法"模式。

八。模式优缺点

   在产口族方向支持开闭原则,在产口等级结构方向不支持开闭原则。

以上是关于设计模式-抽像工厂的主要内容,如果未能解决你的问题,请参考以下文章

设计模式——抽象工厂,简单工厂和工厂方法

PHP 建造者模式

大话设计模式之简单工厂读后感

PHP面向对象之选择工厂和更新工厂

解释器模式

抽像类与接口