【design pattern】工厂方法模式和抽象工厂模式
前言
设计模式分为三大类:
创建型模式:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式;
结构型模式:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式;
行为型模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式;
简单工厂
首先要明确的是,简单工厂模式不属于23种设计模式,它引入了创建者的概念,将实例化的代码从应用代码中抽离,在工厂类的静态方法中只处理被创建的对象,如果业
务需要变更则需要在工厂类中添加具体的实现类,因此维护性较差。以"工厂创建咖啡"为例说明,如下:
1. 物品标识类Coffee和已有的类
package com.oxygen.bean; /**
*
* 咖啡则作为一种抽象概念:拿铁、美式咖啡、卡布奇诺等均为咖啡家族的一种产品
* @author Oxygen
*
*/
public abstract class Coffee { public abstract String desc(); //获取coffee名称 } class Americano extends Coffee { // 美式咖啡 @Override
public String desc() {
return "美式咖啡";
} } class Cappuccino extends Coffee { //卡布奇诺 @Override
public String desc() {
return "卡布奇诺";
} } class Latte extends Coffee { //拿铁 @Override
public String desc() {
return "拿铁";
} }
2. 简单工厂
package com.oxygen.bean; /**
* 创建材料的工厂类
* @author Oxygen
* @date 2018年10月16日
*/
public class SimpleFactory {
/**
*
* @param type 材料类型
* @return
*/
public static Coffee createInstance(String type) {
if ("Americano".equals(type)) {
return new Americano();
} else if ("Cappuccino".equals(type)) {
return new Cappuccino();
} else if ("Latte".equals(type)) {
return new Latte();
} else {
throw new RuntimeException("type[" + type + "]类型不可识别,没有匹配到可实例化的对象!");
}
} public static void main(String[] args) {
System.out.println(SimpleFactory.createInstance("Americano").desc());
System.out.println(SimpleFactory.createInstance("Cappuccino").desc());
System.out.println(SimpleFactory.createInstance("Latte").desc());
}
}
3. 输出结果
美式咖啡
卡布奇诺
拿铁
工厂方法
工厂方法模式其定义了一个创建对象的接口,由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到了子类,也就是说一个工厂只能生成特定的Coffee
1. 工厂类
package com.oxygen.bean; /**
* Coffee工厂
* @author Oxygen
* @date 2018年10月16日
*/
public abstract interface CoffeeFactory {
public abstract Coffee[] createCoffee(); public static void main(String[] args) {
CoffeeFactory chinaCoffeeFactory = new ChinaCoffeeFactory();
Coffee[] chinaCoffees = chinaCoffeeFactory.createCoffee();
System.out.print("中国咖啡工厂可以生产的咖啡有:");
print(chinaCoffees);
CoffeeFactory americaCoffeeFactory = new AmericaCoffeeFactory();
Coffee[] americaCoffees = americaCoffeeFactory.createCoffee();
System.out.print("美国咖啡工厂可以生产的咖啡有:");
print(americaCoffees);
} public static void print(Coffee[] c) {
for (Coffee coffee : c) {
System.out.print(coffee.desc() + " ");
}
System.out.println();
}
} class ChinaCoffeeFactory implements CoffeeFactory { //中国咖啡工厂 @Override
public Coffee[] createCoffee() {
return new Coffee[] { new Cappuccino(), new Latte() };
} } class AmericaCoffeeFactory implements CoffeeFactory { //美国咖啡工厂 @Override
public Coffee[] createCoffee() {
return new Coffee[] { new Americano(), new Latte() };
} }
2. 输出结果
中国咖啡工厂可以生产的咖啡有:卡布奇诺 拿铁
美国咖啡工厂可以生产的咖啡有:美式咖啡 拿铁
抽象工厂
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类,在上述的场景上继续延伸:咖啡工厂做大做强,引入了新的饮品种类:茶、 碳酸饮
料。中国工厂只能制造咖啡和茶,美国工厂只能制造咖啡和碳酸饮料,如果继续使用上述工厂方法方式,除去对应的产品实体类还需要新增2个抽象工厂(茶制造
工厂、碳酸饮料制造工厂),4个具体工厂实现。
随着产品的增多,会导致类爆炸,这显然是不能接受的。所以这里引出一个概念产品家族,在此例子中,不同的饮品就组成我们的饮品家族, 饮品家族开始承担
创建者的责任,负责制造不同的产品。如下:
package com.oxygen.bean;
public interface AbstractDrinksFactory {
Coffee createCoffee(); //制造咖啡
Tea createTea(); //制造茶
Sodas createSodas();//制造碳酸饮料
}
/**
* 中国饮品工厂:制造咖啡与茶
*/
class ChinaDrinksFactory implements AbstractDrinksFactory {
@Override
public Coffee createCoffee() {
return new Latte();
}
@Override
public Tea createTea() {
return new MilkTea();
}
@Override
public Sodas createSodas() {
// TODO Auto-generated method stub
return null;
}
}
/**
* 美国饮品制造工厂:制造咖啡和碳酸饮料
*/
class AmericaDrinksFactory implements AbstractDrinksFactory {
@Override
public Coffee createCoffee() {
// TODO Auto-generated method stub
return new Latte();
}
@Override
public Tea createTea() {
// TODO Auto-generated method stub
return null;
}
@Override
public Sodas createSodas() {
// TODO Auto-generated method stub
return new CocaCola();
}
}
总结
工厂模式可以帮助我们针对抽象接口编程,而不是针对具体类编程,在不同的场景下按具体情况来
1. 简单工厂:不能算是真正意义上的设计模式,但可以将客户程序从具体类解耦;
2. 工厂方法:使用继承,把对象的创建委托给子类,由子类来实现创建方法,可以看作是抽象工厂模式中只有单一产品的情况;
3. 抽象工厂:使对象的创建被实现在工厂接口所暴露出来的方法中;
【design pattern】工厂方法模式和抽象工厂模式的更多相关文章
- python 设计模式之工厂模式 Factory Pattern (简单工厂模式,工厂方法模式,抽象工厂模式)
十一回了趟老家,十一前工作一大堆忙成了狗,十一回来后又积累了一大堆又 忙成了狗,今天刚好抽了一点空开始写工厂方法模式 我看了<Head First 设计模式>P109--P133 这25页 ...
- Java设计模式之【工厂模式】(简单工厂模式,工厂方法模式,抽象工厂模式)
Java设计模式之[工厂模式](简单工厂模式,工厂方法模式,抽象工厂模式) 工厂模式出现的原因 在java中,创建一个对象最简单的方法就是使用new关键字.但在一些复杂的业务逻辑中,创建一个对象不只需 ...
- PHP简单工厂模式、工厂方法模式和抽象工厂模式比较
PHP工厂模式概念:工厂模式是一种类,它具有为您创建对象的某些方法.您可以使用工厂类创建对象,而不直接使用 new.这样,如果您想要更改所创建的对象类型,只需更改该工厂即可.使用该工厂的所有代码会自动 ...
- PHP简单工厂模式、工厂方法模式和抽象工厂模式
PHP工厂模式概念:工厂模式是一种类,它具有为您创建对象的某些方法.您可以使用工厂类创建对象,而不直接使用 new.这样,如果您想要更改所创建的对象类型,只需更改该工厂即可.使用该工厂的所有代码会自动 ...
- JAVA中的工厂方法模式和抽象工厂模式
工厂方法模式: 定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类.类型:创建类模式类图: 类图知识点:1.类图分为三部分,依次是类名.属性.方法2.以& ...
- iOS常用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)
1. 简单工厂模式 如何理解简单工厂,工厂方法, 抽象工厂三种设计模式? 简单工厂方法包含:父类拥有共同基础接口,具体子类实现子类特殊功能,工厂类根据参数区分创建不同子类实例.该场景对应的UML图如下 ...
- iOS经常使用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)
1. 简单工厂模式 怎样理解简单工厂,工厂方法. 抽象工厂三种设计模式? 简单工厂的生活场景.卖早点的小摊贩.他给你提供包子,馒头,地沟油烙的煎饼等,小贩是一个工厂.它生产包子,馒头,地沟油烙的煎饼. ...
- Java开发中的23中设计模式详解(一)工厂方法模式和抽象工厂模式
一.设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接 ...
- c#工厂模式与抽象工厂模式
一. 工厂方法(Factory Method)模式 工厂方法(FactoryMethod)模式是类的创建模式,其用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中. 工厂方法模式是简单工 ...
随机推荐
- (转)Sql Server 保留几位小数的两种做法
原文地址:http://blog.csdn.net/skyandcode/article/details/23523815 问题: 数据库里的 float momey 类型,都会精确到多位小数.但有时 ...
- iOS端样式错位
在iOS端上点击的时候触发点会在当前元素上方,原因是在最外层使用了fixed定位,换成绝对或相对定位解决问题
- iOS 消除Xcode警告
- undeclared selector #pragma clang diagnostic push #pragma clang diagnostic ignored"-Wundeclar ...
- iOS 集成React Native到现有iOS应用(Ficow本人实测,Xcode 8.3,iOS 10.3)
详细操作步骤,请 参考官方文档 或者翻译文档 ! 我补充一些必要的注意事项: 1.引入React.a文件.配置User Header Search Paths 引入React.a文件(点击+可以看到 ...
- for循环的阶乘
方法一: long sum=0; long num=1; for (long i = 1; i <=20; i++) { for(long j=i;j>0;j--){ num=num*j; ...
- 437 Path Sum III 路径总和 III
给定一个二叉树,二叉树的每个节点含有一个整数.找出路径和等于给定数的路径总数.路径不需要从根节点开始,也不需要在叶节点结束,当路径方向必须是向下的(只从父节点到子节点).二叉树不超过1000个节点,节 ...
- python_基础部分(1)
第1章 Python介绍 1.1 基础介绍 l 代码:代码的出现是为了解决生活中的问题 l 编译解释器:目的是让解释器将代码翻译成计算机可识别的语言 l 编程语言:按照一定规则写出来的语言, C ...
- sdut1642Simple Arithmetics(模拟)
链接 发个长长的模拟 这题要注意的地方挺多 -的个数 以及对齐的情况 全都注意好了 大数的加减乘就可以了 #include <iostream> #include<cstdio> ...
- echart动态加载数据
<!DOCTYPE html> <head> <meta charset="utf-8"> <title>EChar ...
- AJPFX关于this用法和注意事项
this:代表对象.就是所在函数所属对象的引用.哪个对象调用了this所在的函数,this就代表哪个对象,就是哪个对象的引用.开发时在定义功能时,如果该功能内部使用到了调用该功能的对象,这时就用thi ...