3.java设计模式之工厂模式
基本需求:
- 一个披萨店需要订购不同种类的披萨
传统方式:
实现思路
- 在订购类中根据用户不同的输入直接创建不同的披萨实体类进行返回
UML类图
代码实现
披萨类
// 抽象父类
public abstract class Pizza { String name; public abstract void prepare(); public void bake() {
System.out.println(this.name + "披萨烘焙中");
} public void cut() {
System.out.println(this.name + "披萨切割中");
} public void box() {
System.out.println(this.name + "披萨打包中");
} } // 奶酪披萨 子类1
public class CheesePizza extends Pizza { public CheesePizza(String name) {
this.name = name;
} @Override
public void prepare() {
System.out.println(this.name + "披萨准备原材料中");
} }
// 希腊披萨 子类2
public class GreekPizza extends Pizza{ public GreekPizza(String name) {
this.name = name;
} @Override
public void prepare() {
System.out.println(this.name + "披萨准备原材料中");
} }
订购类
public class PizzaStore { public static void main(String[] args) {
new PizzaStore().OrderPizza();
} // 订购披萨方法 传统方式直接采用new出子类的方法进行返回对应的披萨
public void OrderPizza() {
Pizza pizza;
Scanner scanner = new Scanner(System.in);
String orderType;
while (true) {
System.out.println("输入披萨的种类:");
orderType = scanner.nextLine();
if (StringUtils.equals("cheese", orderType)) {
pizza = new CheesePizza("cheese");
} else if (StringUtils.equals("greek", orderType)) {
pizza = new GreekPizza("greek");
} else {
System.out.println("没有该类型的披萨");
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
} }
缺陷及改进:
- 在订购方法中,直接采用new出子类的方法进行返回对应的披萨,违反了设计模式的ocp原则,即对扩展开放,对修改关闭。即当我们给类增加新功能的时候,尽量不修改代码,或者尽可能少修改代码
- 如果新增加一种类型的披萨,则需要修改OrderPizza的方法实现,如果有多个创建Pizza的方法则都需要修改
- 把创建Pizza对象封装到一个类中,这样我们有新的Pizza种类时,只需要修改该类就可,其它有创建Pizza对象的代码就不需要修改了——>简单工厂模式
简单工厂模式:
简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式
简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)
当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式
实现思路
- 创建一个简单工厂类SimpleFactory,提供一个创建Pizza的方法,PizzaStore想要Pizza时,直接在工厂中获取即可
UML类图
代码实现
// 简单工厂类 Pizza类及实现类同上
public class SimpleFactory { // 创建Pizza的方法 可在多个地方调用,如果需要增加其他种类的Pizza则只需要修改此方法内部的实现即可,不需要调用方
public Pizza createPizza(String orderType) {
Pizza pizza = null;
if (StringUtils.equals("cheese", orderType)) {
pizza = new CheesePizza("cheese");
} else if (StringUtils.equals("greek", orderType)) {
pizza = new GreekPizza("greek");
} else {
System.out.println("没有该类型的披萨");
}
return pizza;
} // 简单工厂也叫静态工厂 可直接提供静态的方法获取对象
public static Pizza createPizza1(String orderType) {
Pizza pizza = null;
if (StringUtils.equals("cheese", orderType)) {
pizza = new CheesePizza("cheese");
} else if (StringUtils.equals("greek", orderType)) {
pizza = new GreekPizza("greek");
} else {
System.out.println("没有该类型的披萨");
}
return pizza;
} }
public class PizzaStore { public static void main(String[] args) {
// new PizzaStore().OrderPizza();
new PizzaStore(new SimpleFactory());
} private SimpleFactory simpleFactory; public PizzaStore(SimpleFactory simpleFactory) {
this.simpleFactory = simpleFactory;
OrderPizza();
} private void OrderPizza() {
Pizza pizza;
Scanner scanner = new Scanner(System.in);
String orderType;
while (true) {
System.out.println("输入披萨的种类:");
orderType = scanner.nextLine();
// 通过Pizza工厂获取Pizza对象
pizza = simpleFactory.createPizza(orderType);
if (null == pizza) {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
} }
工厂方法模式:
在上面的基础上增加了新的需求,需要在每种pizza上加上产地,例如 北京的奶酪pizza、北京的胡椒pizza或者是伦敦的奶酪pizza、伦敦的胡椒pizza
思路1:可以使用简单工厂模式,新建两个简单工厂,BJPizzaSimpleFactory和LDPizzaSimpleFactory 但是考虑到项目的规模,以及软件的可维护性、可扩展性并不是特别好
思路2:采用工厂方法模式
- 将披萨项目的实例化功能抽象成抽象方法,在不同的口味点餐子类中具体实现
- 工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
实现思路
- 在PizzaStore中增加一个创建Pizza抽象方法,由BJPizzaStore和LDPizzaStore去实现,至此该两个子类创建的Pizza都是各自地区的
UML类图
代码实现
// 含有抽象方法的抽象类
public abstract class PizzaStore { public static void main(String[] args) {
// 根据地区选工厂? 没品出来和创建多个简单工厂有什么好处
String area = "BJ";
if (area.equals("BJ")) {
new BJPizzaStore();
} else {
new LDPizzaStore();
}
} public PizzaStore() {
OrderPizza();
} private void OrderPizza() {
Pizza pizza;
Scanner scanner = new Scanner(System.in);
String orderType;
while (true) {
System.out.println("输入披萨的种类:");
orderType = scanner.nextLine();
// 使用抽象方法来创建Pizza,使用不同的实现类将会得到不同的披萨
pizza = createPizza(orderType);
if (null == pizza) {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
} // 创建Pizza的抽象方法 由子类实现
public abstract Pizza createPizza(String orderType); }
// 子类1
public class BJPizzaStore extends PizzaStore { @Override
public Pizza createPizza(String orderType) {
Pizza pizza = null;
if (StringUtils.equals("cheese", orderType)) {
pizza = new BJCheesePizza("BJCheese");
} else if (StringUtils.equals("pepper", orderType)) {
pizza = new BJPepperPizza("BJPepper");
} else {
System.out.println("没有该类型的披萨");
}
return pizza;
}
} // 子类2
public class LDPizzaStore extends PizzaStore { @Override
public Pizza createPizza(String orderType) {
Pizza pizza = null;
if (StringUtils.equals("cheese", orderType)) {
pizza = new BJCheesePizza("LDCheese");
} else if (StringUtils.equals("pepper", orderType)) {
pizza = new BJPepperPizza("LDPepper");
} else {
System.out.println("没有该类型的披萨");
}
return pizza;
}
}
抽象工厂模式:
抽象工厂模式定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类,可以将简单工厂模式和工厂方法模式进行整合
从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象),将工厂抽象成两层,
实现思路
- 创建AbsFactory( 抽象工厂) 和具体实现的工厂子类,使用时创建工厂子类即可
UML类图
代码实现
// 抽象工厂类
public interface AbsFactory { Pizza createPizza(String orderType); } // 子类1
public class BJFactory implements AbsFactory { @Override
public Pizza createPizza(String orderType) {
Pizza pizza = null;
if (StringUtils.equals("cheese", orderType)) {
pizza = new BJCheesePizza("BJCheese");
} else if (StringUtils.equals("pepper", orderType)) {
pizza = new BJPepperPizza("BJPepper");
} else {
System.out.println("没有该类型的披萨");
}
return pizza;
} } // 子类2
public class LDFactory implements AbsFactory { @Override
public Pizza createPizza(String orderType) {
Pizza pizza = null;
if (StringUtils.equals("cheese", orderType)) {
pizza = new BJCheesePizza("LDCheese");
} else if (StringUtils.equals("pepper", orderType)) {
pizza = new BJPepperPizza("LDPepper");
} else {
System.out.println("没有该类型的披萨");
}
return pizza;
} }
public class PizzaStore { public static void main(String[] args) {
new PizzaStore(new BJFactory());
} private AbsFactory factory; public PizzaStore(AbsFactory factory) {
// 在此处声明需要工厂类对象 , 使用时直接创建抽象工厂的子类对象即可
this.factory = factory;
OrderPizza();
} private void OrderPizza() {
Pizza pizza;
Scanner scanner = new Scanner(System.in);
String orderType;
while (true) {
System.out.println("输入披萨的种类:");
orderType = scanner.nextLine();
// 使用抽象方法来创建Pizza,使用不同的实现类将会得到不同的披萨
pizza = factory.createPizza(orderType);
if (null == pizza) {
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
} }
jdk源码:
在Calendar类中的getInstance()方法中有用到简单工厂模式
public static Calendar getInstance()
{
// 获取默认的zone和aLocale
return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
} public static Calendar getInstance(TimeZone zone,
Locale aLocale)
{
return createCalendar(zone, aLocale);
} private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
if (provider != null) {
try {
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
} Calendar cal = null;
// 此处使用了简单工厂模式来创建Calender对象 通过aLocale不同的后缀
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
} ...... return cal;
}
注意事项:
- 意义:将实例化对象的的代码抽取出来,放到一个类中同一管理和维护,在项目中达到依赖解耦的目的,提高项目的扩展性和维护性
- 依赖抽象原则(尽量依赖抽象的东西)
- 创建对象时,不要使用new,而是将new的东西放在一个工厂中并返回
- 不要让类继承一个具体的类,而是继承抽象类或者实现接口,不要覆盖基类汇总已经实现的方法
3.java设计模式之工厂模式的更多相关文章
- 浅析JAVA设计模式之工厂模式(一)
1 工厂模式简单介绍 工厂模式的定义:简单地说,用来实例化对象,取代new操作. 工厂模式专门负责将大量有共同接口的类实例化.工作模式能够动态决定将哪一个类实例化.不用先知道每次要实例化哪一个类. 工 ...
- Java设计模式之工厂模式(Factory模式)介绍(转载)
原文见:http://www.jb51.net/article/62068.htm 这篇文章主要介绍了Java设计模式之工厂模式(Factory模式)介绍,本文讲解了为何使用工厂模式.工厂方法.抽象工 ...
- Java 设计模式之工厂模式(二)
原文地址:Java 设计模式之工厂模式(二) 博客地址:http://www.extlight.com 一.背景 本篇内容是 Java 设计模式创建型模式的第二篇.上一篇主题为 <Java 设计 ...
- 浅析JAVA设计模式之工厂模式(二)
1 工厂方法模式简单介绍 工厂方法 (Factroy Method)模式:又称多态性工厂模式(Polymorphic Factory),在这样的模式中,核心工厂不再是一个详细的类.而是一个抽象工厂,提 ...
- java设计模式2————工厂模式
1.工厂模式介绍: 1.1.实现了创建者与调用者的分离 1.2.详细分类: 简单工厂模式 工厂方法模式 抽象工厂模式 1.3.所遵循的OOP原则: 开闭原则:对扩展开放,对修改关闭 依赖倒转原则:面向 ...
- java 设计模式之工厂模式与反射的结合
工厂模式: /** * @author Rollen-Holt 设计模式之 工厂模式 */ interface fruit{ public abstract void eat(); } ...
- JAVA设计模式--抽象工厂模式
抽象工厂设计模式 1.系统中有多个产品族,而系统一次只可能消费其中一族产品2.同属于同一个产品族的产品以其使用.来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):抽象工厂角色: 这是工厂方法模式的 ...
- Java设计模式之-----工厂模式(简单工厂,抽象工厂)
一.工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的. 工厂模式在<Java与模式>中分为三类:1)简单工厂模式(Simple Factor ...
- Java设计模式之工厂模式(简单工厂模式+工厂方法模式)
摘自http://blog.csdn.net/jason0539/article/details/23020989 在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是 ...
- java设计模式之一工厂模式
简单工厂模式是java设计模式中最简单的设计模式之一: 工厂模式是最常用的设计模式之一. 工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模 ...
随机推荐
- rustup命令速度慢
通过以下命令更换镜像: $ENV:RUSTUP_DIST_SERVER='https://mirrors.ustc.edu.cn/rust-static' $ENV:RUSTUP_UPDATE_ROO ...
- 吐血分享一款免费看所有付费影视的app,不好用来石欠我
前言 朋友经常找我要各种付费影视资源,在下逛遍各大网站,终于找到一款app,那简直是神器啊. 几乎各大主流平台的付费影视都能观看,亲测有效.还在浏览器一个一个搜资源而费劲?? 还在为只买了一个平台的V ...
- 16.Android-activity生命周期与启动模式
1.activity共有4个状态 如下图所示: 运行状态 如果一个活动位于屏幕的前台(可见的),那么它就是活动的或正在运行的. 暂停状态 如果一个活动失去了焦点,但仍然可见(也就是说,一个新的非全尺寸 ...
- 2017年 实验五 B2B模拟实验
实验五 B2B模拟实验 [实验目的] ⑴.掌握B2B中供应商的供求信息发布.阿里商铺开设和订单交易等过程. ⑵.掌握B2B中采购商的采购信息的发布.交易洽谈.网上支付和收货等过程. [实验条件] ⑴ ...
- python练习三角形,99乘法
#方案一:# result=0# #列# for i in range(1,10):# #行# for j in range(1,i+1):# result=i*j# print('%d*%d=%d' ...
- 多测师讲解python ____字典,字符,元组,集合(转换)___高级讲师肖sir
1.字符转换 a =['a','b','c','d','e'] #定义一个列表b =[1,2,3,4,5] #定义一个列表c=zip(a,b)# zip类:可以将两个列表进行拼接,返回一个列表且列表中 ...
- Git之多人协同开发
一.获取远程库信息 1 2 3 $ git remote -v origin https://github.com/xxxxx/node.git (fetch) origin https://gi ...
- python程序整理(2)
# 写一个函数完成三次登陆功能: # 用户的用户名密码从一个文件register中取出. # register文件包含多个用户名,密码,用户名密码通过|隔开,每个人的用户名密码占用文件中一行. # 完 ...
- 【原创】xenomai内核解析--双核系统调用(二)--应用如何区分xenomai/linux系统调用或服务
版权声明:本文为本文为博主原创文章,转载请注明出处.如有错误,欢迎指正. 1. 引出问题 上一篇文章xenomai内核解析--双核系统调用(一)以X86处理器为例,分析了xenomai内核调用的流程, ...
- pycharm2018.3.5 下载激活(windows平台)
软件下载: 百度网盘下载 提取码: 73p7 激活操作: 1.下载jar包 JetbrainsCrack-4.2-release-enc.jar 链接:https://pan.baidu.com/s/ ...