zoukankan      html  css  js  c++  java
  • 设计模式(二 & 三)工厂模式:3-抽象工厂模式

    •  什么是抽象工厂?

      抽象工厂模式,引入了“产品族”的概念。

      何为产品族?还是以 设计模式(二)工厂模式:2-工厂方法模式 提到的 Operation 为例。

      之前讨论的都是局限于 Operation 这个产品,这是一个由“工厂”做出来的产品,而至于是哪一个工厂做出来的产品,我们并不关心。

      抽象工厂模式关注的就是这一点,现在为其加上前缀:“工厂1生产的 Operation”,“工厂2生产的 Operation”。

      这就是产品族,对象拥有相同的行为,但却是有不同的实现。

    • 模拟场景:

       Operation 在这个并不能很好地体现 抽象工厂 的优势,我们换一个例子:

      现在,我需要去创建用户(User)和部门(Department)两个对象,但是底层需要用的数据库(DB2 和 MySQL),可能产生变化,所以需要两套解决方案。

    • 思想:

      首先,针对需要创建的对象,需要一个抽象工厂(AbsFactory),负责创建抽象用户(AbsUser)和抽象部门(AbsDepartment)。

      根据底层的数据库,抽象工厂拥有两个实现,DB2 工厂(FactoryDB2)和 MySQL 工厂(FactoryMySQL)。

      每个工厂各司其职,创建对应的继承抽象类的对象。

    • UML

      

    • UML 分析:

      这是一个针对给出情景的完整 UML 类图。

      为用户(AbsUser)定义了两种行为,而部门(AbsDepartment)没有定义行为。

      从 UML 就可以看出,抽象工厂,是对 工厂方法 的一种延伸,FactoryDB2 和 FactoryMySQL 起着 AbsOperationFactory 的作用。

      将工厂方法的 AbsOperationFactory 转为实例工厂,并在之上加上一个抽象层,就是抽象工厂。

    • 代码:
    public abstract class AbsFactory {
    
        public abstract AbsUser createUser();
    
        public abstract AbsDepartment createDepartment();
    }
    public final class FactoryDB2 extends AbsFactory {
    
        @Override
        public UserDB2 createUser() {
            return new UserDB2();
        }
    
        @Override
        public DepartmentDB2 createDepartment() {
            return new DepartmentDB2();
        }
    }
    public final class FactoryMySQL extends AbsFactory {
    
        @Override
        public UserMySQL createUser() {
            return new UserMySQL();
        }
    
        @Override
        public DepartmentMySQL createDepartment() {
            return new DepartmentMySQL();
        }
    }
    public abstract class AbsUser {
    
        protected boolean hasRegistered = false;
    
        protected void joinDepartment(AbsDepartment department) {
            if (hasRegistered) {
                System.out.println(this + " join " + department);
            } else {
                System.out.println(this + " not registered cannot join department");
            }
        }
    
        protected abstract void register();
    
        @Override
        public String toString() {
            return "User[" + this.getClass().getSimpleName() + ":" + this.hashCode() + "]";
        }
    }
    public final class UserDB2 extends AbsUser {
    
        @Override
        public void register() {
            super.hasRegistered = true;
            System.out.println(this + "register success");
        }
    }
    public final class UserMySQL extends AbsUser {
    
        @Override
        public void register() {
            super.hasRegistered = false;
            System.out.println(this + "register failure");
        }
    }
    public abstract class AbsDepartment {
    
        @Override
        public String toString() {
            return "Department[" + this.getClass().getSimpleName() + ":" + this.hashCode() + "]";
        }
    }
    public final class DepartmentDB2 extends AbsDepartment {
    
    }
    public final class DepartmentMySQL extends AbsDepartment {
    
    }
    • 客户端的调用代码:
    public final class AbsFactoryTest {
    
        @Test
        void testFactoryDB2() {
            AbsFactory factory = new FactoryDB2();
            AbsUser user = factory.createUser();
            AbsDepartment department = factory.createDepartment();
            user.register();
            user.joinDepartment(department);
        }
    
        @Test
        void testFactoryMySQL() {
            AbsFactory factory = new FactoryMySQL();
            AbsUser user = factory.createUser();
            AbsDepartment department = factory.createDepartment();
            user.register();
            user.joinDepartment(department);
        }
    }
    • 优势

      从客户端的调用,我们就可以发现,从创建用户开始,后续的代码都是一致的。

      也就是说,只需要改变顶层的实例工厂,就可以改变具体的行为(到底是 MySQL 还是 DB2)。

      如果需要加入新的工厂,例如 FactoryOracle,不会对现有的代码产生破坏,很好体现了:对扩展开放,对修改关闭。

    • 劣势

      在设计 抽象工厂 时,需要完整地考虑到工厂需要创建哪些东西,在这个例子上就是 User 和 Department。

      如果在设计完毕之后,需要引入新的产品,例如订单 Order 之类的,对于现有代码的结构破坏会很大,从顶层开始就破坏了代码的封装性。

    • 抽象工厂有哪些实际应用?

      数据库的 ORM 框架。

      Java 平台无关的特性。

  • 相关阅读:
    Windows Phone 开发——相机功能开发
    IE8 margin:0 auto 不能居中显示的问题
    YUI Compressor JS和CSS压缩工具使用方式(使用前安装JDK)
    Javascript日常编码中的一些常见问题
    NODESCHOOL
    js动态加载css和js
    JS this用法详解
    getElementsByTagName( )方法
    js 停止事件冒泡 阻止浏览器的默认行为(比如阻止超连接 # )
    跨浏览器的事件对象
  • 原文地址:https://www.cnblogs.com/jing-an-feng-shao/p/7544309.html
Copyright © 2011-2022 走看看