美文网首页
2、创建型模式之抽象工厂

2、创建型模式之抽象工厂

作者: 聂叼叼 | 来源:发表于2018-04-24 22:54 被阅读0次

    一、介绍

    意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
    主要解决:主要解决接口选择的问题。
    何时使用:系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
    如何解决:在一个产品族里面,定义多个产品。
    关键代码:在一个工厂里聚合多个同类产品。
    应用实例:工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,要不然,没法进入共产主义了,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OO 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
    优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
    缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
    使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
    注意事项:产品族难扩展,产品等级易扩展。
    适用性:
    1.一个系统要独立于它的产品的创建、组合和表示时。
    2.一个系统要由多个产品系列中的一个来配置时。
    3.当你要强调一系列相关的产品对象的设计以便进行联合使用时。
    4.当你提供一个产品类库,而只想显示它们的接口而不是实现时。

    二、实例一

    参与者
    1.AbstractFactory
    声明一个创建抽象产品对象的操作接口。
    2.ConcreteFactory
    实现创建具体产品对象的操作。
    3.AbstractProduct
    为一类产品对象声明一个接口。
    4.ConcreteProduct
    定义一个将被相应的具体工厂创建的产品象。
    实现abstractProduct接口。
    5.Client
    仅使用由AbstractFactory和AbstractProduc
    类声明的接口。

    • 类图


      image.png

    AbstractFactory

    package com.nieshenkuan.creational.abstractfactory;
    
    public interface IAnimalFactory {
        
        ICat createCat();
        
        IDog createDog();
    }
    
    

    ConcreteFactory

    package com.nieshenkuan.creational.abstractfactory;
    
    public class BlackAnimalFactory implements IAnimalFactory{
    
        @Override
        public ICat createCat() {
            return new BlackCat();
        }
    
        @Override
        public IDog createDog() {
            return new BlackDog();
        }
    
    }
    
    package com.nieshenkuan.creational.abstractfactory;
    
    public class WhiteAnimalFactory implements IAnimalFactory{
    
        @Override
        public ICat createCat() {
            return new WhiteCat();
        }
    
        @Override
        public IDog createDog() {
            return new WhiteDog();
        }
    
    }
    

    AbstractProduct

    package com.nieshenkuan.creational.abstractfactory;
    
    public interface ICat {
        void eat();
    }
    
    
    package com.nieshenkuan.creational.abstractfactory;
    
    public interface IDog {
        void eat();
    }
    

    ConcreteProduct

    package com.nieshenkuan.creational.abstractfactory;
    
    public class BlackCat implements ICat {
    
        @Override
        public void eat() {
            System.out.println("The black cat is eating!");
        }
    }
    
    package com.nieshenkuan.creational.abstractfactory;
    
    public class WhiteCat implements ICat {
        
        @Override
        public void eat() {
            System.out.println("The white cat is eating!");
        }
    
    }
    
    package com.nieshenkuan.creational.abstractfactory;
    
    public class BlackDog implements IDog {
        @Override
        public void eat() {
            System.out.println("The black dog is eating");
        }
    
    }
    
    package com.nieshenkuan.creational.abstractfactory;
    public class WhiteDog implements IDog {
        @Override
        public void eat() {
            System.out.println("The white dog is eating!");
        }
    
    }
    

    Client

    package com.nieshenkuan.creational.abstractfactory;
    
    public class Test {
    
        public static void main(String[] args) {
            IAnimalFactory blackAnimalFactory = new BlackAnimalFactory();
            ICat blackCat = blackAnimalFactory.createCat();
            blackCat.eat();
            IDog blackDog = blackAnimalFactory.createDog();
            blackDog.eat();
    
            IAnimalFactory whiteAnimalFactory = new WhiteAnimalFactory();
            ICat whiteCat = whiteAnimalFactory.createCat();
            whiteCat.eat();
            IDog whiteDog = whiteAnimalFactory.createDog();
            whiteDog.eat();
    
        }
    
    }
    

    结果:

    The black cat is eating!
    The black dog is eating
    The white cat is eating!
    The white dog is eating!
    

    三、实例二

    我们将创建 Shape 和 Color 接口和实现这些接口的实体类。下一步是创建抽象工厂类 AbstractFactory。接着定义工厂类 ShapeFactory 和 ColorFactory,这两个工厂类都是扩展了 AbstractFactory。然后创建一个工厂创造器/生成器类 FactoryProducer。
    AbstractFactoryPatternDemo,我们的演示类使用 FactoryProducer 来获取 AbstractFactory 对象。它将向 AbstractFactory 传递形状信息 Shape(CIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。同时它还向 AbstractFactory 传递颜色信息 Color(RED / GREEN / BLUE),以便获取它所需对象的类型。

    抽象工厂.jpg
    步骤 1
    为形状创建一个接口。
    Shape.java
    package com.nieshenkuan.creational.abstractfactory.demo;
    /**
     * 为形状创建一个接口。
     * @author NSK
     *
     */
    public interface Shape {
        void draw();
    }
    

    步骤 2
    创建实现接口的实体类。
    Rectangle.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    /**
     * 创建实现接口的实体类。
     * @author NSK
     *
     */
    public class Rectangle implements Shape {
        @Override
        public void draw() {
            System.out.println("Inside Rectangle::draw() method.");
        }
    }
    

    Square.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    
    /**
     * 创建实现接口的实体类。
     * 
     * @author NSK
     *
     */
    public class Square implements Shape {
    
        @Override
        public void draw() {
            System.out.println("Inside Square::draw() method.");
        }
    }
    

    Circle.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    
    /**
     * 创建实现接口的实体类。
     * 
     * @author NSK
     *
     */
    public class Circle implements Shape {
    
        @Override
        public void draw() {
            System.out.println("Inside Circle::draw() method.");
        }
    }
    

    步骤 3
    为颜色创建一个接口。
    Color.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    /**
     * 为颜色创建一个接口。
     * @author NSK
     *
     */
    public interface Color {
        void fill();
    }
    

    步骤4
    创建实现接口的实体类。
    Red.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    
    /**
     * 创建实现接口的实体类。
     * 
     * @author NSK
     *
     */
    public class Red implements Color {
    
        @Override
        public void fill() {
            System.out.println("Inside Red::fill() method.");
        }
    }
    

    Green.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    
    public class Green implements Color {
    
           @Override
           public void fill() {
              System.out.println("Inside Green::fill() method.");
           }
        }
    

    Blue.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    
    public class Blue implements Color {
    
        @Override
        public void fill() {
            System.out.println("Inside Blue::fill() method.");
        }
    }
    

    步骤 5
    为 Color 和 Shape 对象创建抽象类来获取工厂。
    AbstractFactory.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    
    public abstract class AbstractFactory {
        
        abstract Color getColor(String color);
    
        abstract Shape getShape(String shape);
    }
    

    步骤 6
    创建扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象。
    ShapeFactory.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    
    public class ShapeFactory extends AbstractFactory {
    
        @Override
        public Shape getShape(String shapeType) {
            if (shapeType == null) {
                return null;
            }
            if (shapeType.equalsIgnoreCase("CIRCLE")) {
                return new Circle();
            } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
                return new Rectangle();
            } else if (shapeType.equalsIgnoreCase("SQUARE")) {
                return new Square();
            }
            return null;
        }
    
        @Override
        Color getColor(String color) {
            return null;
        }
    }
    

    ColorFactory.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    
    public class ColorFactory extends AbstractFactory {
    
        @Override
        public Shape getShape(String shapeType) {
            return null;
        }
    
        @Override
        Color getColor(String color) {
            if (color == null) {
                return null;
            }
            if (color.equalsIgnoreCase("RED")) {
                return new Red();
            } else if (color.equalsIgnoreCase("GREEN")) {
                return new Green();
            } else if (color.equalsIgnoreCase("BLUE")) {
                return new Blue();
            }
            return null;
        }
    }
    

    步骤 7
    创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂。
    FactoryProducer.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    
    public class FactoryProducer {
        public static AbstractFactory getFactory(String choice) {
            if (choice.equalsIgnoreCase("SHAPE")) {
                return new ShapeFactory();
            } else if (choice.equalsIgnoreCase("COLOR")) {
                return new ColorFactory();
            }
            return null;
        }
    }
    

    步骤 8
    使用 FactoryProducer 来获取 AbstractFactory,通过传递类型信息来获取实体类的对象。
    AbstractFactoryPatternDemo.java

    package com.nieshenkuan.creational.abstractfactory.demo;
    
    public class AbstractFactoryPatternDemo {
        public static void main(String[] args) {
    
            // 获取形状工厂
            AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
    
            // 获取形状为 Circle 的对象
            Shape shape1 = shapeFactory.getShape("CIRCLE");
    
            // 调用 Circle 的 draw 方法
            shape1.draw();
    
            // 获取形状为 Rectangle 的对象
            Shape shape2 = shapeFactory.getShape("RECTANGLE");
    
            // 调用 Rectangle 的 draw 方法
            shape2.draw();
    
            // 获取形状为 Square 的对象
            Shape shape3 = shapeFactory.getShape("SQUARE");
    
            // 调用 Square 的 draw 方法
            shape3.draw();
    
            // 获取颜色工厂
            AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
    
            // 获取颜色为 Red 的对象
            Color color1 = colorFactory.getColor("RED");
    
            // 调用 Red 的 fill 方法
            color1.fill();
    
            // 获取颜色为 Green 的对象
            Color color2 = colorFactory.getColor("Green");
    
            // 调用 Green 的 fill 方法
            color2.fill();
    
            // 获取颜色为 Blue 的对象
            Color color3 = colorFactory.getColor("BLUE");
    
            // 调用 Blue 的 fill 方法
            color3.fill();
        }
    }
    

    步骤 9
    验证输出。

    Inside Circle::draw() method.
    Inside Rectangle::draw() method.
    Inside Square::draw() method.
    Inside Red::fill() method.
    Inside Green::fill() method.
    Inside Blue::fill() method.
    

    四、实例三

    例子背景:
    随着客户的要求越来越高,宝马车需要不同配置的空调和发动机等配件。于是这个工厂开始生产空调和发动机,用来组装汽车。这时候工厂有两个系列的产品:空调和发动机。宝马320系列配置A型号空调和A型号发动机,宝马230系列配置B型号空调和B型号发动机。
    概念:
    抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象。比如宝马320系列使用空调型号A和发动机型号A,而宝马230系列使用空调型号B和发动机型号B,那么使用抽象工厂模式,在为320系列生产相关配件时,就无需制定配件的型号,它会自动根据车型生产对应的配件型号A。

    针对百度百科上对于抽象工厂模式的简介,结合本例如下:

    当每个抽象产品都有多于一个的具体子类的时候(空调有型号A和B两种,发动机也有型号A和B两种),工厂角色怎么知道实例化哪一个子类呢?比如每个抽象产品角色都有两个具体产品(产品空调有两个具体产品空调A和空调B)。抽象工厂模式提供两个具体工厂角色(宝马320系列工厂和宝马230系列工厂),分别对应于这两个具体产品角色,每一个具体工厂角色只负责某一个产品角色的实例化。每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。

    抽象工厂模式代码

    产品类 :

    //发动机以及型号    
    public interface Engine {    
      
    }    
    
    public class EngineA implements Engine{    
        public EngineA(){    
            System.out.println("制造-->EngineA");    
        }    
    }    
    
    public class EngineB implements Engine{    
        public EngineB(){    
            System.out.println("制造-->EngineB");    
        }    
    }    
    
    //空调以及型号    
    public interface Aircondition {    
      
    }    
    
    public class AirconditionA implements Aircondition{    
        public AirconditionA(){    
            System.out.println("制造-->AirconditionA");    
        }    
    }    
    
    public class AirconditionB implements Aircondition{    
        public AirconditionB(){    
            System.out.println("制造-->AirconditionB");    
        }    
    }   
    

    创建工厂类:

    //创建工厂的接口    
    public interface AbstractFactory {    
        //制造发动机  
        public Engine createEngine();  
        //制造空调   
        public Aircondition createAircondition();   
    }    
    
    //为宝马320系列生产配件    
    public class FactoryBMW320 implements AbstractFactory{    
            
        @Override    
        public Engine createEngine() {      
            return new EngineA();    
        }    
        @Override    
        public Aircondition createAircondition() {    
            return new AirconditionA();    
        }    
    }    
    
    //宝马523系列  
    public class FactoryBMW523 implements AbstractFactory {    
        
         @Override    
        public Engine createEngine() {      
            return new EngineB();    
        }    
        @Override    
        public Aircondition createAircondition() {    
            return new AirconditionB();    
        }    
    }   
    

    客户:

    public class Customer {    
        public static void main(String[] args){    
            //生产宝马320系列配件  
            FactoryBMW320 factoryBMW320 = new FactoryBMW320();    
            factoryBMW320.createEngine();  
            factoryBMW320.createAircondition();  
                
            //生产宝马523系列配件    
            FactoryBMW523 factoryBMW523 = new FactoryBMW523();    
            factoryBMW320.createEngine();  
            factoryBMW320.createAircondition();  
        }    
    }  
    
    总结:
    无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,
    他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,
    因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,
    稍加修改,加入了一个新方法后,
    由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,
    当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。
           所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。
    

    2018/04/24

    相关文章

      网友评论

          本文标题:2、创建型模式之抽象工厂

          本文链接:https://www.haomeiwen.com/subject/eheakftx.html