香雨站

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 96|回复: 0

一篇打通架构设计,java设计模式7,工厂方法模式

[复制链接]

3

主题

6

帖子

11

积分

新手上路

Rank: 1

积分
11
发表于 2022-9-22 16:12:39 | 显示全部楼层 |阅读模式
一、工厂模式

工厂模式也称简单工厂模式,是创建型设计模式的一种,这种设计模式提供了按需创建对象的最佳方式。同时,这种创建方式不会对外暴露创建细节,通常会通过一个统一的接口创建所需对象。
定义一个创建对象的接口,让其子类自己决定将哪一个工厂类实例化,工厂模式使创建过程延迟到子类中进行。
简单地说,就是为了给代码结构提供扩展性,屏蔽每一个功能类中的具体实现逻辑。这种方式便于外部更加简单地调用,同时也是去掉众多ifelse的最佳手段。当然,这种设计模式也有一些缺点,例如需要实现的类比较多、难以维护。开发成本高等,但这些问题都可以通过结合不同的设计模式逐步优化。
二、工厂方法模式的优缺点

1、优点

(1)良好的封装性、代码结构清晰。
如一个调用者想创建一个对象,只需要知道其名称即可,降低了模板间的耦合。
(2)扩展性好。
如果想增加一个产品,只需扩展一个工厂类即可。
(3)屏蔽产品类
调用者只关心产品的接口。
(4)典型的解耦框架
2、缺点

每增加一个产品,就需要增加一个产品工厂的类,增加了系统的复杂度。
三、模拟场景

通过普通用户、京东plus、企业采购购买《Java核心技术》书籍为例,不同的购买人,优惠和流程都是不一样的。
三种用户的购买接口:
序号类型接口
11void buySaviourByGeneralUser(int productId)
22double buySaviourByJDPlus(int productId, int vipLevel, boolean promotions)
33Sring buySaviourByEnterprise(int productId, String company, String name)
普通用户、京东plus、企业采购三个接口的接口参数不同,返回值也不同。
四、违背原则方案

1、思路清晰,简单明了

如果增加其它类型,继续增加ifelse即可。
2、但是,似乎违反了一些设计原则:


  • 单一职责原则:指一个类或者模块应该有且只有一个改变的原因。
  • 开闭原则:软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的。
  • 接口隔离原则:尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口中只包含客户感兴趣的方法。
package com.guor.beanutil.factory;

public class Shopping {

    public static void main(String[] args) {
        // 普通用户1
        buyBook(1, 1, 1);
        // 京东plus2
        buyBook(1, 1, 2);
        // 企业采购3
        buyBook(1, 1, 3);
    }

    /**
     * 购买Java核心技术
     *
     * 一顿操作猛如虎,实际购买流程比这个复杂的多,只是简单模拟
     */
    public static void buyBook(int productId, int userId, int userType) {
        // 按照不同的用户类型(普通用户1、京东plus2、企业采购3)
        if (userType == 1) {// 普通用户1
            // 购买Java核心技术
            buyBookByGeneralUser(productId);
        } else if (userType == 2) {// 京东plus2
            // 通过userId到数据库查询会员等级,优惠力度不一样
            int vipLevel = 1;
            // 通过产品id查询商品是否参加活动
            boolean promotions = true;

            // 购买Java核心技术
            buyBookByJDPlus(productId, vipLevel, promotions);
        } else if (userType == 3) {// 企业采购3
            // 根据userId到company表中查询
            String company = "哪吒技术有限公司";
            // 根据userId到用户表查询
            String name = "哪吒";

            // 购买Java核心技术
            buyBookByEnterprise(productId, company, name);
        }
    }

    /**
     * 普通用户1
     *
     * @param productId 商品id
     */
    public static void buyBookByGeneralUser(int productId){
        // 一些不为人知的业务处理
        System.out.println("普通用户购买了Java核心技术");
    }

    /**
     * 京东plus2
     *
     * @param productId 商品id
     * @param vipLevel 会员等级
     * @param promotions 是否有活动
     * @return 京东plus为您节省了多少钱
     */
    public static double buyBookByJDPlus(int productId, int vipLevel, boolean promotions){
        // 一些不为人知的业务处理
        System.out.println("京东plus购买了Java核心技术");
        return 99;
    }

    /**
     * 企业采购3
     *
     * @param productId 商品id
     * @param company 公司名称
     * @param name 采办人姓名
     * @return 具体采购详情
     */
    public static String buyBookByEnterprise(int productId, String company, String name){
        // 一些不为人知的业务处理
        System.out.println("企业采购了Java核心技术");
        return "哪吒为粉丝采购了Java核心技术";
    }
}
五、通过工厂方法模式重构代码

现将代码通过工厂方法模式进行重构,重构之后,代码会更加的清晰明了,再拓展的时候,,再也不用写那么多的ifelse了,添加接口实现类,并通过工厂类构建实例即可。代码结构清晰明了,可复用性强、拓展性更好,符合何单一职责原则、开闭原则、接口隔离原则。
1、定义购买接口

package com.guor.beanutil.factory;

import java.util.Map;

/**
* 购买《Java核心技术》
*/
public interface IBuyBook {

    void buyBook(Integer productId, Integer userId, Map<String, Object> otherMsg);
}
2、普通用户实现类

package com.guor.beanutil.factory;

import java.util.Map;

/**
* 普通用户1
*/
public class BuyBookByGeneralUser implements IBuyBook {

    @Override
    public void buyBook(Integer productId, Integer userId, Map<String, Object> otherMsg) {
        // 一些不为人知的业务处理
        System.out.println("普通用户购买了Java核心技术");
    }
}
3、京东plus实现类

package com.guor.beanutil.factory;

import java.util.Map;

/**
* 京东plus2
*/
public class BuyBookByJDPlus implements IBuyBook {

    @Override
    public void buyBook(Integer productId, Integer userId, Map<String, Object> otherMsg) {
        // 一些不为人知的业务处理
        System.out.println("京东plus购买了Java核心技术");
    }
}

4、企业采购实现类

package com.guor.beanutil.factory;

import java.util.Map;

/**
* 企业采购3
*/
public class BuyBookByEnterprise implements IBuyBook {
    @Override
    public void buyBook(Integer productId, Integer userId, Map<String, Object> otherMsg) {
        // 一些不为人知的业务处理
        System.out.println("哪吒为粉丝采购了Java核心技术");
    }
}

5、创建用户工厂

这里定义了一个用户的工厂类,在里面按照类型实现不同的用户实例,代码清晰明了,后续新增新用户,在工厂类新增即可。
package com.guor.beanutil.factory;

import java.util.HashMap;
import java.util.Map;

public class BuyBookFactory {

    public IBuyBook getBuyBook(int userType){
        if (userType == 1) {// 普通用户1
            return new BuyBookByGeneralUser();
        } else if (userType == 2) {// 京东plus2
            return new BuyBookByJDPlus();
        } else if (userType == 3) {// 企业采购3
            return new BuyBookByEnterprise();
        }else{
            System.out.println("不存在此用户类型...");
            return null;
        }
    }
6、测试类

    public static void main(String[] args) {
        BuyBookFactory buyBookFactory = new BuyBookFactory();
        // 普通用户1
        IBuyBook buyBook1 = buyBookFactory.getBuyBook(1);
        buyBook1.buyBook(1, 1, null);

        // 京东plus2
        Map<String, Object> map2 = new HashMap<String, Object>();
        map2.put("vipLevel", 1);// 会员等级
        map2.put("promotions", true);// 是否参加活动
        IBuyBook buyBook2 = buyBookFactory.getBuyBook(2);
        buyBook1.buyBook(1, 1, map2);

        // 企业采购3
        Map<String, Object> map3 = new HashMap<String, Object>();
        map3.put("company", "哪吒技术有限公司");// 公司名称
        map3.put("name", "哪吒");// 采办人姓名
        IBuyBook buyBook3 = buyBookFactory.getBuyBook(3);
        buyBook3.buyBook(1,1,map3);
    }
}



在这里插入图片描述

很多人觉得设计模式很简单,但是,能够熟练的将设计模式应用在自己的项目中,将各模块、功能规划的井井有条,运用的炉火纯青、恰到好处,真的很难。反复阅读,仔细体会。
设计模式系列文章:

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|香雨站

GMT+8, 2025-3-15 06:04 , Processed in 0.779828 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.. 技术支持 by 巅峰设计

快速回复 返回顶部 返回列表