zoukankan      html  css  js  c++  java
  • 设计者模式 --- 抽象工厂AbstractFactory

    工厂方法中只考虑生产同级别的产品,对于综合型的工厂,生产较多种类的产品无法使用,如下图,对于一个产品族,可能无法实现,这时需要使用抽象工厂。

     首先看一下抽象工厂的定义:是一种为访问类创建一组相关或相互依赖对象的接口,并且访问类无需指定所需产品,具体类就能得到同族的不同等级的产品的模式结构。

    相当于抽象工厂是工厂方法的升级版本,抽象工厂模式可以生产多个等级的产品。

    使用抽象工厂模式一般需要满足以下条件:

    系统中有多个产品族,每一个具体工厂创建同一族但是不同等级结构的产品

    系统一次只可能消费其中某一族的产品,即同族的产品一起使用

    抽象工厂模式主要优点:

    • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
    • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
    • 系统中有多个可以在类的内部对产品族中相关联的多等级产品共同管理,而不必引入多个新的类来进行管理

    缺点:

    • 当产品族中增加一个新的产品时,所有的工厂多需要进行修改。

    其结构:

    • 抽象工厂(AbstractFactory):提供创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品
    • 具体工厂(ConcreteFactory):实现抽象工厂中的多个抽象方法,完成具体产品的创建
    • 抽象产品(Product):定义了产品的规范,描述厂品的主要特性以及功能,抽象工厂模式有多个抽象产品
    • 具体产品(ConcreteProduct):实现了抽象产品所定义的接口,邮局一工厂来创建,同具体工厂之间就是一对多关系

     接下来看一下代码实现:

    抽象产品1 Product1

    package abstractFactory;
    
    /**
     * 抽象产品1
     */
    public interface Product1 {
    
        void run();
    }

    抽象产品2Produce2

    package abstractFactory;
    
    /**
     * 抽象产品2
     */
    public interface Product2 {
    
        void show();
    }

    具体产品ConcreteProduct11

    package abstractFactory;
    
    /**
     * 具体产品11,实现抽闲产品1的接口
     */
    public class ConcreteProduct11 implements Product1 {
    
        @Override
        public void run() {
            System.out.println("产品11开始跑了");
        }
    }

    具体产品ConcreteProduct12

    package abstractFactory;
    
    /**
     * 具体产品12,实现抽闲产品1的接口
     */
    public class ConcreteProduct12 implements Product1 {
    
        @Override
        public void run() {
            System.out.println("产品12开始跑了");
        }
    }

    具体产品ConcreteProduct21

    package abstractFactory;
    
    /**
     * 具体产品21,实现了抽象产品2的接口
     */
    public class ConcreteProduct21 implements Product2 {
    
        @Override
        public void show() {
            System.out.println("具体产品21开始展示");
        }
    }

    具体产品ConcreteProduct22

    package abstractFactory;
    
    /**
     * 具体产品22,实现了抽象产品2的接口
     */
    public class ConcreteProduct22 implements Product2 {
    
        @Override
        public void show() {
            System.out.println("具体产品22开始展示");
        }
    }

    抽象工厂AbstractFactory

    package abstractFactory;
    
    /**
     * 抽象工厂 定义生产抽象产品 1 2 接口
     */
    public interface AbstractFactory {
    
        /**
         * 产品1
         *
         * @return 产品实例1
         */
        Product1 newProduct1();
    
        /**
         * 产品2
         *
         * @return 产品实例2
         */
        Product2 newProduce2();
    }

    具体工厂1ConcreteFactory1

    package abstractFactory;
    
    /**
     * 具体工厂1 生产具体产品 11 21
     */
    public class ConcreteFactory1 implements AbstractFactory {
    
        @Override
        public Product1 newProduct1() {
            System.out.println("具体工厂1生产了具体产品11");
            return new ConcreteProduct11();
        }
    
        @Override
        public Product2 newProduce2() {
            System.out.println("具体工厂1生产了具体产品21");
            return new ConcreteProduct21();
        }
    }

    具体工厂2ConcreteFactory2

    package abstractFactory;
    
    /**
     * 具体工厂2 生产具体产品 12 22
     */
    public class ConcreteFactory2 implements AbstractFactory {
    
        @Override
        public Product1 newProduct1() {
            System.out.println("具体工厂2生产了具体产品12");
            return new ConcreteProduct12();
        }
    
        @Override
        public Product2 newProduce2() {
            System.out.println("具体工厂2生产了具体产品22");
            return new ConcreteProduct22();
        }
    }

    客户端Client

    package abstractFactory;
    
    
    public class Client {
        public static void main(String[] args) {
            // 模拟根据指定名称实例化工厂
            AbstractFactory abstractFactory = (AbstractFactory) Utils.getObject("ConcreteFactory1");
            // 获取该工厂的产品1
            Product1 product1 = abstractFactory.newProduct1();
            // 获取该工厂的产品2
            Product2 product2 = abstractFactory.newProduce2();
            // 运行产品1
            product1.run();
            // 运行产品2
            product2.show();
        }
    }

    工具类

    package abstractFactory;
    
    public class Utils {
    
        public static Object getObject(String name){
            String cName = "abstractFactory." + name;
            System.out.println("新类名:"+cName);
            Class<?> c = null;
            try {
                // 根据名称获取类
                c = Class.forName(cName);
                // 调用该类的无参构造方法并获取实例
                return c.getDeclaredConstructor().newInstance();
            } catch (Exception e) {
                // 异常
                e.printStackTrace();
                return c;
            }
        }
    }

    输出:

    新类名:abstractFactory.ConcreteFactory1
    具体工厂1生产了具体产品11
    具体工厂1生产了具体产品21
    产品11开始跑了
    具体产品21开始展示

    适用场景:

    • 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
    • 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
    • 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

    源码地址:https://github.com/yang-shixiong/design/tree/master/src/abstractFactory

  • 相关阅读:
    Raft论文的一些问题
    乱序日志同步成员变更方案
    OceanBase RPC机制简要说明
    OceanBase server处理网络包的回调逻辑
    比较下OceanBase的选举协议和Raft的选举协议的区别
    TokuDB调研文档
    给MySQL官方提交的bug report备忘
    记录一个__lll_lock_wait_private错误
    关于MySQL redo log,挖些坑,慢慢填
    A little problem for pt-pmp
  • 原文地址:https://www.cnblogs.com/yangshixiong/p/12567449.html
Copyright © 2011-2022 走看看