尚硅谷设计模式学习(四)工厂模式
从披萨店的案例引入工厂模式
披萨的种类很多(比如 GreekPizza、CheesePizza 等)
- 披萨制作完成后需要进行cut(切片工作),box(包装工作)
- 完成披萨店的功能
一、简单工厂模式
1、基本介绍
简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。定义了一个创建对象的工厂类,由这个工厂类来封装实例化对象的代码。
在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式。
属于创建型模式。
2、代码实现
设计方案: 定义一个可以实例化 Pizaa 对象的工厂类,封装创建对象的代码。
Pizza接口
public interface Pizza {/*** 披萨切片*/void cut();/*** 披萨包装*/void box();
}
奶酪披萨
public class CheesePizza implements Pizza {public void cut() {System.out.println("奶酪披萨切片中");}public void box() {System.out.println("奶酪披萨打包中");}
}
希腊披萨
public class GreekPizza implements Pizza {public void cut() {System.out.println("希腊披萨切片中");}public void box() {System.out.println("希腊披萨打包中");}
}
创建披萨实例的工厂
public class PizzaFactory {public static Pizza getPizza(String type) {if(type.equalsIgnoreCase("CheesePizza")){return new CheesePizza();}else if(type.equalsIgnoreCase("GreekPizza")){return new GreekPizza();}else {return null;}}}
测试
public class Client {public static void main(String[] args) {Pizza cheesePizza = PizzaFactory.getPizza("CheesePizza");cheesePizza.cut();cheesePizza.box();Pizza greekPizza = PizzaFactory.getPizza("GreekPizza");greekPizza.cut();greekPizza.box();}
}
结果
奶酪披萨切片中
奶酪披萨打包中
希腊披萨切片中
希腊披萨打包中
二、工厂方法模式
看一个新的需求,客户在点披萨时,可以点不同口味的披萨,比如北京的奶酪 pizza、北京的胡椒 pizza 或者是伦敦的奶酪 pizza、伦敦的胡椒 pizza。
思路 1
使用简单工厂模式,创建不同的简单工厂类,比如 BJPizzaSimpleFactory,LDPizzaSimpleFactory等等。从当前这个案例来说,也是可以的,但是考虑到项目的规模,以及软件的可维护性、可扩展性并不是特别好。
思路 2
使用工厂方法模式
1、基本介绍
工厂方法模式:定义一个创建对象的抽象方法,由子类工厂决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
2、代码实现
披萨类Pizza
public interface Pizza {/*** 披萨切片*/void cut();/*** 披萨包装*/void box();
}
四种披萨
public class BJChessPizza implements Pizza{public void cut() {System.out.println("北京奶酪披萨切片中");}public void box() {System.out.println("北京奶酪披萨打包中");}
}
public class BJPepperPizza implements Pizza{public void cut() {System.out.println("北京胡椒披萨切片中");}public void box() {System.out.println("北京胡椒披萨打包中");}
}
public class LDChessPizza implements Pizza{public void cut() {System.out.println("伦敦奶酪披萨切片中");}public void box() {System.out.println("伦敦奶酪披萨打包中");}
}
public class LDPepperPizza implements Pizza{public void cut() {System.out.println("伦敦胡椒披萨切片中");}public void box() {System.out.println("伦敦胡椒披萨打包中");}
}
Pizza抽象工厂
public abstract class PizzaFactory {public abstract Pizza getPizza(String type);}
北京披萨工厂,伦敦披萨工厂
public class BJPizzaFactory extends PizzaFactory {@Overridepublic Pizza getPizza(String type) {if(type.equalsIgnoreCase("chess")){return new BJChessPizza();}else if(type.equalsIgnoreCase("pepper")){return new BJPepperPizza();}else {return null;}}
}
public class LDPizzaFactory extends PizzaFactory {@Overridepublic Pizza getPizza(String type) {if(type.equals("chess")){return new LDChessPizza();}else if(type.equals("pepper")){return new LDPepperPizza();}else {return null;}}
}
测试
public class Client {public static void main(String[] args) {//北京披萨工厂BJPizzaFactory bjPizzaFactory = new BJPizzaFactory();Pizza bjChessPizza = bjPizzaFactory.getPizza("chess");bjChessPizza.cut();bjChessPizza.box();Pizza bjPepperPizza = bjPizzaFactory.getPizza("pepper");bjPepperPizza.cut();bjPepperPizza.box();//伦敦披萨工厂LDPizzaFactory ldPizzaFactory = new LDPizzaFactory();Pizza ldChessPizza = ldPizzaFactory.getPizza("chess");ldChessPizza.cut();ldChessPizza.box();Pizza ldPepperPizza = ldPizzaFactory.getPizza("pepper");ldPepperPizza.cut();ldPepperPizza.box();}
}
结果
北京奶酪披萨切片中
北京奶酪披萨打包中
北京胡椒披萨切片中
北京胡椒披萨打包中
伦敦奶酪披萨切片中
伦敦奶酪披萨打包中
伦敦胡椒披萨切片中
伦敦胡椒披萨打包中
三、抽象工厂模式
新需求:有的人喜欢吃肯德基的披萨,有的人喜欢吃麦当劳的披萨
1、基本介绍
抽象工厂模式:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类
2、代码实现
披萨接口
public interface Pizza {/*** 披萨切片*/void cut();/*** 披萨包装*/void box();
}
商店A披萨,商店B披萨接口
public interface ShopAPizza extends Pizza {
}
public interface ShopBPizza extends Pizza {
}
商店A披萨的实现类
public class ShopABJChessPizza implements ShopAPizza{public void cut() {System.out.println("商店A北京奶酪披萨切片中");}public void box() {System.out.println("商店A北京奶酪披萨打包中");}
}
public class ShopALDChessPizza implements ShopAPizza{public void cut() {System.out.println("商店A伦敦奶酪披萨切片中");}public void box() {System.out.println("商店A伦敦奶酪披萨打包中");}
}
商店B披萨的实现类
public class ShopBBJChessPizza implements ShopBPizza{public void cut() {System.out.println("商店B北京胡椒披萨切片中");}public void box() {System.out.println("商店B北京胡椒披萨打包中");}}
public class ShopBLDChessPizza implements ShopBPizza{public void cut() {System.out.println("商店B伦敦胡椒披萨切片中");}public void box() {System.out.println("商店B伦敦胡椒披萨打包中");}}
披萨工厂抽象类
public abstract class PizzaFactory {public abstract Pizza getBJChessPizza(String type);public abstract Pizza getLDChessPizza(String type);
}
商店A,B的工厂类
public class ShopAPizzaFactory extends PizzaFactory {@Overridepublic Pizza getBJChessPizza(String type) {return new ShopABJChessPizza();}@Overridepublic Pizza getLDChessPizza(String type) {return new ShopALDChessPizza();}
}
public class ShopBPizzaFactory extends PizzaFactory {@Overridepublic Pizza getBJChessPizza(String type) {return new ShopBBJChessPizza();}@Overridepublic Pizza getLDChessPizza(String type) {return new ShopBLDChessPizza();}
}
四、JDK中的工厂模式源码案例
比如说日历类Calendar就用到了简单工厂模式
我们一般这样使用
public class Test {public static void main(String[] args) {Calendar cal = Calendar.getInstance();System.out.println("年:" + cal.get(Calendar.YEAR));System.out.println("月:" + (cal.get(Calendar.MONTH) + 1));System.out.println("日:" + cal.get(Calendar.DAY_OF_MONTH));System.out.println("时:" + cal.get(Calendar.HOUR_OF_DAY));System.out.println("分:" + cal.get(Calendar.MINUTE));System.out.println("秒:" + cal.get(Calendar.SECOND));}
}
具体源码:就用到了简单工厂模式
/*** Gets a calendar using the default time zone and locale. The* <code>Calendar</code> returned is based on the current time* in the default time zone with the default* {@link Locale.Category#FORMAT FORMAT} locale.** @return a Calendar.*/public static Calendar getInstance(){return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));}
private static Calendar createCalendar(TimeZone zone,Locale aLocale)
//根据 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;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;}}}if (cal == null) {// If no known calendar type is explicitly specified,// perform the traditional way to create a Calendar:// create a BuddhistCalendar for th_TH locale,// a JapaneseImperialCalendar for ja_JP_JP locale, or// a GregorianCalendar for any other locales.// NOTE: The language, country and variant strings are interned.if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {cal = new BuddhistCalendar(zone, aLocale);} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"&& aLocale.getCountry() == "JP") {cal = new JapaneseImperialCalendar(zone, aLocale);} else {cal = new GregorianCalendar(zone, aLocale);}}return cal;}
五、工厂模式小结
1、工厂模式的意义
将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式
2、三种工厂模式 (简单工厂模式、工厂方法模式、抽象工厂模式)
个人觉得这个区别在于产品,如果产品单一,最合适用工厂模式,但是如果有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。再通俗深化理解下:工厂模式针对的是一个产品等级结构 ,抽象工厂模式针对的是面向多个产品等级结构的。
再来看看工厂方法模式与抽象工厂模式对比:
工厂方法模式 |
抽象工厂模式 |
针对的是一个产品等级结构 | 针对的是面向多个产品等级结构 |
一个抽象产品类 | 多个抽象产品类 |
可以派生出多个具体产品类 | 每个抽象产品类可以派生出多个具体产品类 |
一个抽象工厂类,可以派生出多个具体工厂类 | 一个抽象工厂类,可以派生出多个具体工厂类 |
每个具体工厂类只能创建一个具体产品类的实例 | 每个具体工厂类可以创建多个具体产品类的实例 |
参考文章:(1条消息) 抽象工厂模式-与-工厂方法模式区别_wyxhd2008的博客-CSDN博客
尚硅谷设计模式学习(四)工厂模式相关推荐
- 设计模式 - 学习笔记 - 工厂模式Factory Pattern
设计模式 - 学习笔记 - 工厂模式Factory Pattern 1. 简单工厂 1.1 应用场景 1.2 UML 1.3 优劣分析 好处 缺点 1.4 代码示例 抽象产品 AbstractProd ...
- Java设计模式学习之工厂模式
简单工厂模式 我直接上代码代码里有很详细的注解 //简单工厂模式 是由一个工厂对象决定创建出哪种产品 class Factory1 {publicstatic void main(String[] a ...
- 设计模式学习之工厂模式(附demo)
介绍 工厂模式(Factory Pattern) 是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,我们在创建对象时不会对客户端暴 ...
- 设计模式学习总结——工厂模式
在我们平常创建对象的时候,都是通过关键字 new 来实现的,例: Class A = new A() . 在一些情况下,要创建的对象需要一系列复杂的初始化操作,比如查配置文件.查数据库表.初始化成员对 ...
- Java设计模式学习02——工厂模式
工厂模式 工厂模式主要是为创建对象提供接口,将创建对象的过程隔离起来,实现了创建者与调用者的分离,提高了程序的灵活性. 核心本质: 实例化对象,用工厂方法代替new操作. 将选择实现类.创建对象统一 ...
- 尚硅谷设计模式笔记-装饰者模式
文章目录 一.需求 二.装饰者方法 三.装饰者模式的JDK应用 笔记来源: 尚硅谷 一.需求 星巴克咖啡订单项目(咖啡馆) : 咖啡种类/单品咖啡: Espresso(意大利浓咖啡). ShortBl ...
- 设计模式学习2 工厂模式
工厂模式其实就是简单模式的升级版本, 简单模式将界面与业务逻辑区分开,但是如果不停的增加计算器的运算方式,简单模式中的工厂Factory 中判断的业务逻辑会变非常复杂,这不符合封装的原则. 所以在此之 ...
- 尚硅谷设计模式学习(1)---[设计模式七大原则]
- 尚硅谷设计模式学习(2)---[UML类图]
最新文章
- 443 ERROR [main] client.ConnectionManager$HConnectionImplementation: Can‘t get connection to ZooKeep
- web服务器采用的是什么协议,webservice中采用协议Http,它是指什么意思
- SAP C4C,CRM和S4HANA的Saved Query使用介绍
- wxpython使用实例_wxPython中文教程入门实例
- delphi基本语法
- 开源的类似于Apache ab的压力测试命令行工具SuperBenchmarker
- js使用hover事件做一个“个人中心”的浮动层
- php 函数有命名空间吗_解析 ThinkPHP 的命名空间
- java caller_js中的caller和callee属性
- 百度SEO站群音乐聚合源码/自动采集(在线可播放)
- Windows Server 2008 \u0026 2012在GCE上正式商用了
- ref:LDAP入门
- spring boot设置项目名称
- 手机号空号检测的几点建议
- php加skplayer,WordPress免插件集成ckplayer播放器
- html+移动端图片点击放大,移动端点击图片放大特效PhotoSwipe.js插件实现
- 智能POS删除文件和数据库操作步骤
- 算法竞赛宝典 递归算法 地盘划分
- eclipse新建java项目报错 jrt-fs.jar
- HDU 1870 愚人节的礼物
热门文章
- 学习php技术最快需要多久,学php最快要多久 学习路线
- 计算机房防凝露保温材料,数据中心机房墙面如何做保温?
- 任务车间调度问题的混合整数规划模型
- 水箱建模最小二乘法_lammps软件学习基础操作建模
- “Chain of Thought Reasoning“ 和 “Chain Prompts“ 是什么
- JBoss Seam框架
- 代码实现pe文件图标替换
- 燃料电池聚合物电解质膜高低温退化性能测试中的TEC半导体制冷温控解决方案
- win10s上不了网,网卡代码驱动异常代码56。
- 问题:UltraISO:这个软件有问题,它制作的iso文件会造成无法正确识别。用PowerISO吧...