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() 工厂模 ...
随机推荐
- 如何获取value值,获取属性值,设置属性值,
1.获取select下拉框的value值, 2.获取select 的tid值 3.设置属性值 4.判断哪个单选框选中了 prop好像是判断的意思吧,个人理解勿喷谢谢!!!!!!
- git克隆指定分支到本地
我们每次使用命令 git clone https://xxx.com/android-app.git 默认 clone 的是这个仓库的 master 分支. 使用Git下载指定分支命令为:git cl ...
- Vue 学习 二 路由详解
1 roter-link 和roter-view组件 2路由配置 a.动态路由 b.嵌套路由 c.别名路由 d.命名路由 3 Js操作路由 4 重定向和别名 1为路由默认绑定 2 使用组件 根据 路由 ...
- java性能分析之火焰图
原由 最近因为kafka.zookeeper.ES和相关的Java应用的内存问题搞的头大,做运维将近4年,对Java调优.性能方面的知识了解的少之又少,是时候下定决心来对他多一个学习了.不能一口吃成一 ...
- javascript in IE
前提:一个页面导入若干个js文件 问题: 1.如果其中一个文件出问题可能会导致下面的文件导入失败,如果导入很多外部js库文件,导致错误不好排查,可以调整好js的加载顺序,以免影响页面功能 2.IE获取 ...
- CentOS 7的安装与部署 02
2.2 操作系统安装过程 第01步:加载系统镜像 第02步:启动虚拟主机 第03步:系统安装选择界面修改网卡名称 启动虚拟机后,会出现选择菜单,首先用方向键选择 install centos7选项,然 ...
- zookeeper-(单机,伪集群)
安装zookeeper(单机,伪集群): 1.下载 登陆zookeeper官网下载 https://zookeeper.apache.org/ 或者 https://mirror.bit.e ...
- Monolog - Logging for PHP
github地址:https://github.com/Seldaek/monolog 使用 Monolog 安装 核心概念 日志级别 配置一个日志服务 为记录添加额外的数据 使用通道 自定义日志格式 ...
- python自定义模块引入报错 pycharm
1.首先进入settings->python console 选择Add source roots to PYTHONPATH 2.然后将自己工程文件夹mark as source root 3 ...
- 【转】Centos7系统下忘记了root管理员账号密码的解决方式
哎,事情的起因就是脑子背了,曾经还手贱把root密码改了,导致普通账户改不回管理员账号了,然而,这次是百毒"救"了我,最终完美修改了root密码,好文章特地转载过来了,侵权删. 原 ...