首页 > 其他 > 详细

工厂的建设之路(三)-- 抽象工厂模式

时间:2020-07-16 00:40:59      阅读:39      评论:0      收藏:0      [点我收藏+]

再上一篇博客中谈到了工厂方法模式,它能将对象的创建和产品分离,同时还符合开闭原则,看起来很完美,那么它有缺陷吗?
还是接着我们的登录功能来看,在我们的系统中登录通常伴随着三张表:用户表,角色表,权限表。
那么当我们使用登录功能的时候,可能会用到三种dao:UserDao,RoleDao,PermissionDao。
这个时候我们的实现是适配MySQL的,那么我们需要
三个具体产品类:MySQLUserDao,MySQLRoleDao,MySQLPermissionDao
三个抽象工厂:UserDaoFactory,RoleDaoFactory,PermissionDao
三个具体工厂:MySQLUserDaoFactory,MySQLRoleDaoFactory,MySQLPermissionDaoFactory。
这样我们实现了对一种数据库的兼容,假如我们需要增加对Oracle的兼容:
那么我们又需要增加三个具体产品类,三个具体工厂类。
这样看来我们产品类型稍微多一点的时候,工厂方法模式会造成类的数量爆炸增长,那么如何解决这个问题呢?
这样需要今天的主角登场--抽象工厂模式

抽象工厂模式

当我们看到需要多种(这里的多种是指不是同一抽象产品的实现类)产品来实现一类功能的时候,我们可以考虑将产品进行分组,上面的例子可以很明显看到,我们将MySQLUserDao,MySQLRoleDao,MySQLPermissionDao分为一组,然后将这样的一组产品用一个工厂创建,我们称这样的一组产品为一个“产品族”。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、更有效率。
下面我们用代码演示:

抽象产品和他们的实现:

public interface UserDao {
    void getUser();
}

class MySQLUserDao implements UserDao {
    @Override
    public void getUser() {
        System.out.println("MySQL get user");
    }
}

class OracleUserDao implements UserDao {

    @Override
    public void getUser() {
        System.out.println("Oracle get user");
    }
}

public interface RoleDao {
    void getRole();
}

class MySQLRoleDao implements RoleDao {
    @Override
    public void getRole() {
        System.out.println("MySQL get role");
    }
}

class OracleRoleDao implements RoleDao {
    @Override
    public void getRole() {
        System.out.println("Oracle get role");
    }
}

public interface PermissionDao {
    void getPermission();
}
class MySQLPermissionDao implements PermissionDao {

    @Override
    public void getPermission() {
        System.out.println("MySQL get permission");
    }
}

class OraclePermissionDao implements PermissionDao {

    @Override
    public void getPermission() {
        System.out.println("Oracle get permission");
    }
}

抽象工厂和它的实现:

public interface AbstractDaoFactory {
    UserDao getUserDao();
    RoleDao getRoleDao();
    PermissionDao getPermissionDao();
}

class MySQLDaoFactory implements AbstractDaoFactory {
    @Override
    public UserDao getUserDao() {
        return new MySQLUserDao();
    }

    @Override
    public RoleDao getRoleDao() {
        return new MySQLRoleDao();
    }

    @Override
    public PermissionDao getPermissionDao() {
        return new MySQLPermissionDao();
    }
}

class OracleDaoFactory implements AbstractDaoFactory {

    @Override
    public UserDao getUserDao() {
        return new OracleUserDao();
    }

    @Override
    public RoleDao getRoleDao() {
        return new OracleRoleDao();
    }

    @Override
    public PermissionDao getPermissionDao() {
        return new OraclePermissionDao();
    }
}

客户端的用法:

// 同样用一个配置文件动态配置
public class PropertiesUtil {
    public static Object getBean(String key) {
        try(InputStream inputStream = new FileInputStream("src/main/java/create/abstractFactory/application.properties")) {
            Properties properties = new Properties();
            properties.load(inputStream);
            String property = properties.getProperty(key);
            Class<?> clazz = Class.forName(property);
            return clazz.newInstance();
        }  catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

// 客户端的用法
public class Client {
    public static void main(String[] args) {
        AbstractDaoFactory daoFactory = (AbstractDaoFactory) PropertiesUtil.getBean("dao-factory");
        daoFactory.getUserDao().getUser();
        daoFactory.getRoleDao().getRole();
        daoFactory.getPermissionDao().getPermission();
    }
}

抽象工厂的优缺点

我们可以看到抽象工厂相较于工厂方法模式大大简化了系统的复杂度,这是显而易见的优点,但是会带来什么问题呢?试想一下,如果关于用户的操作再增加一个表,那么需要再增加一个Dao层的维护,这样一来我们的每个工厂实现和客户端的代码都需要修改,这显然是不符合开闭原则的,但是如果我们时新增一个SQLServer的实现,那么我们只需要增加一个工厂的实现类就可以了,而不用修改原来的任何代码,这样看起来它又是符合开闭原则的。我们把这种现象称为开闭原则的倾斜性。
这样看来,抽象工厂模式并不比工厂方法更优秀,它们是各有取舍,所以程序员在软件设计的时候就需要结合业务多方考量,选用最合适的模式来构建自己程序,这也是对程序员业务理解能力的考验。

三种工厂的总结:

  1. 简单工厂模式:将产品的创建和使用分开,符合单一职责原则,但是没有做到对修改封闭,对扩展开放,不符合开闭原则,不是GOF23种设计模式之一,但是也是一种简单实用的模式。
  2. 工厂方法模式:完美的符合了单一职责原则和开闭原则,但是面对多种产品时会造成系统复杂度急剧上升,反而降低了系统的可维护性。
  3. 抽象工厂模式:将产品分组,一个工厂生产多种产品,加重了工厂的责任,但是极大的简化了系统复杂度,不完全符合开闭原则,对同样的产品族扩展支持友好,一旦产品族需要修改,那么系统的修改难度极大。

工厂的建设之路(三)-- 抽象工厂模式

原文:https://www.cnblogs.com/barneycs/p/13311246.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!