设计模式之工厂模式(Java篇)

  • 创建型模式-工厂模式

在设计模式中,工厂模式可以说是非常实用的一种设计模式,利用抽象工厂模式解耦上层引用和底层实现,能极大的提高代码扩展性,后期维护起来不会一改就是几十个类了,来吧,好好的说道说道工厂模式。
我会尽可能详细阐述清楚该模式所表达的一种设计思想,结尾给出一个利用抽象工厂模式,创建中间层,提出一个开发中因为未解耦而造成维护困难的的解决方案。

  • 注意:文章中阐述的三种工厂模式代码是隔离的,为了使类或接口命名贴切其功能,三类方式里,命名可能重复,如果想写代码完整跑一遍,请建立三个不同包,在对应的包下,去创建相应类或接口。

一、简单工厂模式

  • 说明:简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
以手机为例来说明
  • 定义一个接口,开机的时候,手机界面上,会显示该手机品牌。
  • 此处定义的接口不使用“I”做前缀的这种形式,直接用“Phone”更加形象贴切,类似Map,List。
  • 注意:接口的命名,返回值类型,传值类型都很重要,开发前要考虑好。
public interface Phone {
    /**
     * 实施开机操作的时候,返回手机品牌
     * @return 手机品牌
     */
    String startUp();

}
  • 创建一个小米手机类,这个对象有“开机”功能,实现Phone接口,返回“小米”手机品牌
public class XiaoMiPhone implements Phone {
    @Override
    public String startUp() {
        return "小米";
    }
}
  • 同上,创建一个华为手机类
public class HuaWeiPhone implements Phone {
    @Override
    public String startUp() {
        return "华为";
    }
}
  • 创建手机工厂管理类
public class PhoneFactory {
    private static Phone mPhone;

    //根据品牌关键字获取相应手机对象
    public static Phone createPhone(String Brand) {
        switch (Brand) {
            case "小米":
                mPhone = new XiaoMiPhone();
                break;
            case "华为":
                mPhone = new HuaWeiPhone();
                break;
        }
        return mPhone;
    }
    
}
  • 使用
public void test() {
    Phone xiaoMi = PhoneFactory.createPhone("小米");
    Phone huaWei = PhoneFactory.createPhone("华为");

    System.out.print(xiaoMi.startUp() + "\n");
    System.out.print(huaWei.startUp() + "\n");
}
  • 结果显示
小米
华为
  • 总结下:
    • 简单工厂模式就是把功能类,放进一个工厂类中管理,通过传入相应“关键字”,获取不同的功能类对象。
    • 这里使用了接口,规范了功能类对外暴露的方法,获取对象时只需要使用接口去定义对象,通过工厂类去获取不同实现。
    • 不使用接口定义接受:
      • 如果某些实现类中,有创建特殊方法,接口定义公共方法无法满足,想使用此类特殊方法,使用该类的类型去接受创建的对象
      • 如果只是使用接口,去接受其实现方法,便没法使用相应类中的特殊定义的方法
      • 具体场景,可做相应变通
    • 其实,使用接口规范后,简单工厂模式就和抽象工厂模式就十分相似了!

二、工厂模式

  • 工厂模式区别与简单工厂模式的是,工厂模式不是用一个统一的工厂类来管理所有对象,而是每一个对象都有不同的工厂相对应。
继续以手机为例说明
  • 为了让实例更加完整,此处将上述相同的代码再次复写一遍,为了不做复读机,相关说明省略。疑惑的翻阅下简单工厂模式。
  • 定义手机接口
public interface Phone {
    /**
     * 实施开机操作的时候,返回手机品牌
     * @return 手机品牌
     */
    String startUp();

}
  • 创建一个小米手机类
public class XiaoMiPhone implements Phone {
    @Override
    public String startUp() {
        return "小米";
    }
}
  • 创建一个华为手机类
public class HuaWeiPhone implements Phone {
    @Override
    public String startUp() {
        return "华为";
    }
}

可以看到,底层逻辑实现接口方法方式,这边并未做改动。实际三种工厂模式,底层逻辑实现都用接口规范。

接下来,需要针对小米和华为手机这俩个实现类,去构建不同的工厂,这边用接口去规范不同的工厂类

  • 手机工厂接口
public interface PhoneFactory {
    /**
     * 获取相关手机实例
     * @return 返回实现接口Phone的实例
     */
    Phone getPhone();
}

  • 创建小米手机工厂
public class XiaoMiPhoneFactory implements PhoneFactory {
    @Override
    public Phone getPhone() {
        return new XiaoMiPhone();
    }
}

  • 创建华为手机工厂
public class HuaWeiPhoneFactory implements PhoneFactory {
    @Override
    public Phone getPhone() {
        return new HuaWeiPhone();
    }
}


  • 使用
public void test() {
    PhoneFactory xiaoMiFactory = new XiaoMiPhoneFactory();
    PhoneFactory huaWeiFactory = new HuaWeiPhoneFactory();

    System.out.print(xiaoMiFactory.getPhone().startUp() + "\n");
    System.out.print(huaWeiFactory.getPhone().startUp() + "\n");
}

  • 结果显示
小米
华为

总结下:

  • 这种针对每个对象,去建立不同工厂类,我个人感觉,有点佛了。

三、抽象工厂模式

  • 抽象模式是对工厂模式的进一步优化,工厂类不单单只能创建一个对象,而是能创建一组对象。
  • 在这里,大家可能存在一个疑惑,简单工厂不也是创建一组对象吗?是的,在这点上,俩者是非常非常相似的,区别在于:简单工厂模式是外部传值进去,以获取不同对象;抽象工厂模式直接通过方法获取对象,不需要传值(这里,你可能会想,这不就是把创建对象方法拆开,用不同的方法去标识吗? 这里面的门道还是不一样的,大家对比下,底下阐述的俩种方式,心里应该就有数了)。
继续以手机为例说明
  • 为了用例完整性,继续写出所有代码
  • 定义一个Phone接口
public interface Phone {
    /**
     * 实施开机操作的时候,返回手机品牌
     * @return 手机品牌
     */
    String startUp();

}

  • 创建小米手机类
public class XiaoMiPhone implements Phone {
    @Override
    public String startUp() {
        return "小米";
    }
}

  • 创建华为手机类
public class HuaWeiPhone implements Phone {
    @Override
    public String startUp() {
        return "华为";
    }
}

至此,三类工厂底层实现都是:实现共性接口。区别是是对工厂类的不同构建,下面来看看抽象工厂的工厂类构建。
  • 咱们用俩方式来看看,中间工厂类来创建一组对象

1、第一种方式

  • 定义一个接口,这个接口里面是获取一系列的手机品牌的实例
public interface PhoneBrand {
    /**
     * 获取小米手机实例
     * @return 
     */
    Phone getXiaoMi();
    
    /**
     * 获取华为手机实例
     * @return
     */
    Phone getHuaWei();
}

  • 实现抽象工厂的这个接口
public class PhoneFactory implements PhoneBrand {
    @Override
    public Phone getXiaoMi() {
        return new XiaoMiPhone();
    }

    @Override
    public Phone getHuaWei() {
        return new HuaWeiPhone();
    }
}

  • 使用
public void test() {
    PhoneBrand phoneBrand = new PhoneFactory();

    Phone xiaoMi = phoneBrand.getXiaoMi();
    Phone huaWei = phoneBrand.getHuaWei();

    System.out.print(xiaoMi.startUp() + "\n");
    System.out.print(huaWei.startUp() + "\n");
}

  • 结果显示
小米
华为

2、第二种方式

  • 在这里思考下,抽象工厂模式,是在工厂类里面创建一组对象,与外层交互,不是通过关键字去返回相应对象,而是通过某个共性方法去返回“符合条件的实例”。
  • 这里假设一个场景:我们定义的手机对象,其中的开机功能,只在对应的手机上才会起作用(小米手机想开机,只能使用小米手机类中的开机方法,华为也是如此),在这里,假设此款手机是华为手机。
  • 此处,我们不定义接口,直接创建抽象工厂类。
public class PhoneFactory {
    private static Phone instance;

    public static Phone getInstance() {
        if("XiaoMi".equals(android.os.Build.BRAND))
        {
            return new XiaoMiPhone();
        }
        if("HuaWei".equals(android.os.Build.BRAND))
        {
            return new XiaoMiPhone();
        }
        return null;
    }


    public static Phone getSingleInstance() {
        if (instance == null) {
            synchronized (PhoneFactory.class) {
                if("XiaoMi".equals(android.os.Build.BRAND))
                {
                    instance = new XiaoMiPhone();
                }
                if("HuaWei".equals(android.os.Build.BRAND))
                {
                    instance = new HuaWeiPhone();
                }
                instance = null;
            }
        }
        return instance;
    }
}

  • 使用
public static void test() {
    Phone phone = PhoneFactory.getInstance();
    if (phone == null) return;

    System.out.print(phone.startUp() + "\n");
}

  • 结果显示
华为

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值