步入正题之前可先预习一下之前有讲过的
假设有这么一个场景
有一个Pizza店 需要制作Pizza,首先要考虑这几种情况
-
制作Pizza的步骤:选择食材,制作过程(蒸烤、切片、打包)
常规思路下我们会怎么做呢?
-
首先肯定会写一个抽象类,将Pizza制作方法抽象出来,假设其他步骤都一样((
蒸烤、切片、打包
),那么就需要将选材这个方法进行抽象。 -
其次我们需要制作什么Pizza就直接继承这个抽象类,不同的Pizza实现不同的选
-
最后准备一个Pizza店或者订单,来判断需要什么pizza,然后进行制作
传统代码实现如下:
Pizza抽象类:
//将Pizza 类做成抽象
public abstract class Pizza {
protected String name; //名字
//准备原材料, 不同的披萨不一样,因此,我们做成抽象方法
public abstract void prepare();
public void bake() {
System.out.println(name + " baking;");
}
public void cut() {
System.out.println(name + " cutting;");
}
//打包
public void box() {
System.out.println(name + " boxing;");
}
public void setName(String name) {
this.name = name;
}
}
不同种类Pizza实现:
public class PepperPizza extends Pizza {
@Override
public void prepare() {
// TODO Auto-generated method stub
System.out.println(" 给胡椒披萨准备原材料 ");
}
}
Pizza订单/需求代码
public class OrderPizza {
// 构造器
public OrderPizza() {
Pizza pizza = null;
String orderType; // 订购披萨的类型
do {
orderType = getType();
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName(" 希腊披萨 ");
} else if (orderType.equals("cheese")) {
pizza = new CheesePizza();
pizza.setName(" 奶酪披萨 ");
} else if (orderType.equals("pepper")) {
pizza = new PepperPizza();
pizza.setName("胡椒披萨");
} else {
break;
}
//输出pizza 制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
客户需求/需要什么要的Pizaa(相当于Client)
//相当于一个客户端,发出订购
public class PizzaStore {
public static void main(String[] args) {
// TODO Auto-generated method stub
new OrderPizza();
}
}
通过以上代码可以得出结论:
如果新增了Pizza种类后,那么就需要继承Pizza抽象类;并且订单的代码还需要修改(增加if、else),而且如果其他地方也有使用的话,也会需要修改,影响使用。
并且违反了设计模式的OCP原则,即对扩展开放,对修改关闭
那么如何解决这种方式的弊端呢?
思路:
把创建Pizza对象封装到一个类中,这样我们有了新的Pizza种类时,只需要修改该类即可,其他有创建Pizza对象的代码就不需要修改了,那么就是我们的简单工厂模式
简单工厂模式
又称:静态工厂
概念:
简单工厂模式属于创建型模式,是工厂模式的一种,简单工厂模式是由一个工厂对象决定创建哪一种产品类的实例。
简单模式中,定义了一个创建对象的类,由这个类来封装实例化对象的行为。
当我们用到大量创建某种、某类或者某对象时就会使用到工厂模式。
UML类图:
如图所示:
我们在需要订购Pizza,直接去找工厂类(SimpleFactory),让SimpleFactory去完成生产Pizza的任务。这样再有新的Pizza直接修改SimpleFactory就可以,不需要改动 订单代码
代码改动:
只需要增加SimpleFactory 让订单Pizza与其发生聚合就可以了。
//简单工厂类
public class SimpleFactory {
//更加orderType 返回对应的Pizza 对象
public Pizza createPizza(String orderType) {
Pizza pizza = null;
System.out.println("使用简单工厂模式");
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName(" 希腊披萨 ");
} else if (orderType.equals("cheese")) {
pizza = new CheesePizza();
pizza.setName(" 奶酪披萨 ");
} else if (orderType.equals("pepper")) {
pizza = new PepperPizza();
pizza.setName("胡椒披萨");
}
return pizza;
}
//简单工厂模式 也叫 静态工厂模式
public static Pizza createPizza2(String orderType) {
Pizza pizza = null;
System.out.println("使用简单工厂模式2");
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName(" 希腊披萨 ");
} else if (orderType.equals("cheese")) {
pizza = new CheesePizza();
pizza.setName(" 奶酪披萨 ");
} else if (orderType.equals("pepper")) {
pizza = new PepperPizza();
pizza.setName("胡椒披萨");
}
return pizza;
}
}
OrderPizza代码修改:
这里 与SimpleFactory 采用的是聚合关系,从外部传进来的
public class OrderPizza {
//定义一个简单工厂对象 这里采用的是聚合关系
SimpleFactory simpleFactory;
Pizza pizza = null;
//构造器
public OrderPizza(SimpleFactory simpleFactory) {
setFactory(simpleFactory);
}
public void setFactory(SimpleFactory simpleFactory) {
String orderType = ""; //用户输入的
this.simpleFactory = simpleFactory; //设置简单工厂对象
do {
orderType = getType();
pizza = this.simpleFactory.createPizza(orderType);
//输出pizza
if(pizza != null) { //订购成功
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println(" 订购披萨失败 ");
break;
}
}while(true);
}
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
OrderPizza2的修改:
简单工厂模式 也叫 静态工厂模式
所以这个类(OrderPizza2)主要是针对方法2(createPizza2)去进行修改
public class OrderPizza2 {
Pizza pizza = null;
String orderType = "";
// 构造器
public OrderPizza2() {
do {
orderType = getType();
pizza = SimpleFactory.createPizza2(orderType);
// 输出pizza
if (pizza != null) { // 订购成功
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println(" 订购披萨失败 ");
break;
}
} while (true);
}
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
测试:
//相当于一个客户端,发出订购
public class PizzaStore {
public static void main(String[] args) {
// TODO Auto-generated method stub
//new OrderPizza();
//使用简单工厂模式
//new OrderPizza(new SimpleFactory());
//System.out.println("~~退出程序~~");
//使用静态工厂模式
new OrderPizza2();
}
}
好了简单工厂模式(静态工厂)就讲到这里了
工厂方法模式
新需求:
假设Pizza有不同口味的,比如:有北京奶酪Pizza 北京的胡椒Pizza;或者是伦敦的奶酪Pizza 伦敦的胡椒Pizza
思路1:
使用简单工厂模式,创建不同的工厂类,比如BJPizzaSimplieFactory、LONDONPizzaSimpleFactory等等,但是这样的话,可用性 可扩展性和可维护性不是特别好,以及项目的规模这都是需要考虑的因素。
思路2:
使用工厂方法模式
介绍:
将pizza项目的实例化功能抽象成抽象方法,在不同的
什么是工厂方法模式?
定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类
UML图:
根据新需求代码如下
Pizza抽象类:同上
BJCheesePizza:
public class BJCheesePizza extends Pizza {
@Override
public void prepare() {
// TODO Auto-generated method stub
setName("北京的奶酪pizza");
System.out.println(" 北京的奶酪pizza 准备原材料");
}
}
BJPepperPizza:
public class BJPepperPizza extends Pizza {
@Override
public void prepare() {
// TODO Auto-generated method stub
setName("北京的胡椒pizza");
System.out.println(" 北京的胡椒pizza 准备原材料");
}
}
LDCheesePizza:
public class LDCheesePizza extends Pizza{
@Override
public void prepare() {
// TODO Auto-generated method stub
setName("伦敦的奶酪pizza");
System.out.println(" 伦敦的奶酪pizza 准备原材料");
}
}
LDPepperPizza:
public class LDPepperPizza extends Pizza{
@Override
public void prepare() {
// TODO Auto-generated method stub
setName("伦敦的胡椒pizza");
System.out.println(" 伦敦的胡椒pizza 准备原材料");
}
}
OrderPizza:
public abstract class OrderPizza {
//定义一个抽象方法,createPizza , 让各个工厂子类自己实现
abstract Pizza createPizza(String orderType);
// 构造器
public OrderPizza() {
Pizza pizza = null;
String orderType; // 订购披萨的类型
do {
orderType = getType();
pizza = createPizza(orderType); //抽象方法,由工厂子类完成
//输出pizza 制作过程
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} while (true);
}
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
BJOrderPizza
继承OrderPizza,将创建Pizza下沉到子类BJOrderPizza,看子类和谁关联:
是OrderPizza的具体实现
public class BJOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if(orderType.equals("cheese")) {
pizza = new BJCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new BJPepperPizza();
}
// TODO Auto-generated method stub
return pizza;
}
}
LDOrderPizza
继承OrderPizza,将创建Pizza下沉到子类LDOrderPizza,看子类和谁关联:
是OrderPizza的具体实现
public class LDOrderPizza extends OrderPizza {
@Override
Pizza createPizza(String orderType) {
Pizza pizza = null;
if(orderType.equals("cheese")) {
pizza = new LDCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new LDPepperPizza();
}
// TODO Auto-generated method stub
return pizza;
}
}
测试:
public class PizzaStore {
public static void main(String[] args) {
String loc = "bj";
if (loc.equals("bj")) {
//创建北京口味的各种Pizza
new BJOrderPizza();
} else {
//创建伦敦口味的各种Pizza
new LDOrderPizza();
}
// TODO Auto-generated method stub
}
}
好了工厂方法模式到这里就结束了 你了解了吗 ?接下来看一看抽象工厂模式吧
抽象工厂模式
UML类图:
概念:
定义一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类
抽象工厂模式可以将简单工厂和工厂方法模式进行简单的整合
将工厂抽象成两层,AbstrantFactory(抽象工厂)和具体实现的工厂子类。程序员可以根据创建对象类型适用对应的工厂子类。这样将单个的简单工厂类变成工厂簇,更有利于代码的维护和扩展
代码实现:
💡之前的BJCheesePizza、BJPepperPizza、LDCheesePizza、LDPepperPizza、Pizza抽象类都是之前的
我们先来完成AbsFactory 抽象工厂接口
AbsFactory :
//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
//让下面的工厂子类来 具体实现
public Pizza createPizza(String orderType);
}
再来创建两个工厂子类
BJFactory:
实现AbsFactory 工厂子类
//这是工厂子类
public class BJFactory implements AbsFactory {
@Override
public Pizza createPizza(String orderType) {
System.out.println("~使用的是抽象工厂模式~");
// TODO Auto-generated method stub
Pizza pizza = null;
if(orderType.equals("cheese")) {
pizza = new BJCheesePizza();
} else if (orderType.equals("pepper")){
pizza = new BJPepperPizza();
}
return pizza;
}
}
LDFactory
实现AbsFactory 工厂子类
public class LDFactory implements AbsFactory {
@Override
public Pizza createPizza(String orderType) {
System.out.println("~使用的是抽象工厂模式~");
Pizza pizza = null;
if (orderType.equals("cheese")) {
pizza = new LDCheesePizza();
} else if (orderType.equals("pepper")) {
pizza = new LDPepperPizza();
}
return pizza;
}
}
OrderPizza:
和之前的OrderPizza没有太大区别
会聚合一个AbsFactory 抽象工厂类 通过set()方法进行设置 具体是哪个工厂的子类
public class OrderPizza {
AbsFactory factory;
// 构造器
public OrderPizza(AbsFactory factory) {
setFactory(factory);
}
private void setFactory(AbsFactory factory) {
Pizza pizza = null;
String orderType = ""; // 用户输入
this.factory = factory;
do {
orderType = getType();
// factory 可能是北京的工厂子类,也可能是伦敦的工厂子类
pizza = factory.createPizza(orderType);
if (pizza != null) { // 订购ok
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
} else {
System.out.println("订购失败");
break;
}
} while (true);
}
// 写一个方法,可以获取客户希望订购的披萨种类
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza 种类:");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
测试
public class PizzaStore {
public static void main(String[] args) {
// TODO Auto-generated method stub
//new OrderPizza(new BJFactory());
new OrderPizza(new LDFactory());
}
}
小结:
将实例化对象提取出来,放到一个类中统一维护和管理。达到和主项目的依赖关系的解耦。从而提高项目的扩展性和维护性。
设计模式的依赖抽象原则
创建对象实例时,不要直接new类,而是把这个new类的动作放在一个工厂方法中,并返回,有的书上说变量不要直接持有具体类的引用。
不要让类继承具体类,而是继承抽象类或者是实现interface(接口)
不要覆盖基类中已经实现的方法。
以上就是设计模式中的工厂模式的全部讲解了。你学会了了吗?关注我后续带你解析更多的设计模式
原文始发于微信公众号(码上遇见你):一篇文章带你读懂设计模式之工厂模式
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/79048.html