博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Head First 设计模式 --4 工厂模式 抽象工厂模式
阅读量:5134 次
发布时间:2019-06-13

本文共 2982 字,大约阅读时间需要 9 分钟。

(用到了依赖倒置原则)

我们写的代码中,有的时候可能会出现根据外面给定的不同的参数在方法中根据参数实例化不同的实例,就是会根据不同的参数会new出不同的实例。如果这么写了,这段代码会非常的脆弱,一旦出现新的类型,那么就需要重写将这段代码找出来添加写的new。

之前说过针对接口编程,而不是针对实现。这句话也可以理解成,代码中尽量不要出现具体的实例。能用到实例的地方,应该用超类来代替,通过多态让代码走正确的分支。

通过例子来说明(看的就是《Head First 设计模式》这本书,所有还是用书中的例子)

不用工厂模式,我们就是这么写

Pizza orderPizza(String type){    Pizaa pizza;    if (type.equals("cheese")) {        pizza = new CheesePizza();    } else if (type.equals("clam")) {        pizza = new ClamPizza();    }    pizza.prepare();    pizza.bake();    //.........}

 

通过工厂模式

Pizza orderPizza(String type) {    Pizza pizza = factory.createPizze("cheese");    pizza.prepare();    pizza.bake();    // .........    return pizza;  }class SimplePizzaFactory {  public Pizza createPizze(String type) {    Pizza pizza = null;    if (type.equals("cheese")) {      pizza = new CheesePizza();    } else if (type.equals("clam")) {      pizza = new ClamPizza();    }    return pizza;  }}

这么一看,我们似乎什么也没干,只是将代码搬到了另外一个地方。但是注意到,修改后的方法中,没有new,以后如果有新的类型的Pizza只需要修改这段代码就可以了,orderPizza的方法不用动。工厂模式就这么简单。还有另外一种类型的工厂模式,用静态方法返回实例对象,这种叫静态工厂。

class SimplePizzaFactory {  public static Pizza createCheesePizze() {    return new CheesePizza();  }  public static Pizza createClamPizze() {    return new ClamPizza();  }}

这就是工厂模式。其实工厂模式像是一种编程习惯。然后说一下抽象工厂模式。

抽象工厂模式的作用是建立一个产品家族的抽象类型,这个类型的子类定义了实例化实例的方法,想要获取实例,首先要实例这个类型的实例,在将这个实例传入某个工厂中。抽象工厂一般配合着工厂模式使用。抽象工厂的具体工厂通常用工厂方法创建。工厂模式的主要作用是创建类的实例,抽象工厂的作用是创建一系列的实例。

根据上面修改看一下抽象工厂的代码

interface Pizza {  public void prepare();  public void bake();}class NSCheesePizza implements Pizza {  @Override  public void prepare() {}  @Override  public void bake() {}}class NSClamPizza implements Pizza {  @Override  public void prepare() {}  @Override  public void bake() {}}class ChicagoCheesePizza implements Pizza {  @Override  public void prepare() {}  @Override  public void bake() {}}class ChicagoClamPizza implements Pizza {  @Override  public void prepare() {}  @Override  public void bake() {}}abstract class PizzaStore {  public Pizza orderPizza(String type) {    Pizza pizza = null;    pizza = createPizza(type);    pizza.prepare();    pizza.bake();    return pizza;  }  abstract Pizza createPizza(String type);}class NYPizzaStore extends PizzaStore {  @Override  Pizza createPizza(String type) {    if (type.equals("chesse")) {      return new NSCheesePizza();    }    return null;  }}class ChicagoPizzaStore extends PizzaStore {  @Override  Pizza createPizza(String type) {    if (type.equals("chesse")) {      return new ChicagoCheesePizza();    }    return null;  }}
public class Test {  public static void main(String[] args) {    PizzaStore nyStore = new NYPizzaStore();    Pizza pizza = nyStore.orderPizza("cheese");  }}

这里用到了依赖倒置原则。怎么倒置的,开始时需要制作不同的pizza,不同的具体类,这样所有的pizza店都会依赖这些具体类。于是,抽象出来了一个Pizza,这样就需要一个pizza工厂,然后所有的pizza类都依赖这样一个抽象,并且pizza店也需要这个抽象。这样我们就倒置了商店依赖具体pizza类的设计。

怎么才能避免违反依赖倒置原则:

1、变量不可以持有具体类的引用。(避免使用new)
2、不要让类派生具体类。
3、不要覆盖基类已经实现的方法。(如果覆盖了基类的方法,就说明这个类不是一个真正适合的抽象类)

转载于:https://www.cnblogs.com/badboyf/p/6212464.html

你可能感兴趣的文章
ionic2+ 基础
查看>>
MyBaits动态sql语句
查看>>
用户空间与内核空间,进程上下文与中断上下文[总结]
查看>>
JAVA开发环境搭建
查看>>
Visual Studio基于CMake配置opencv1.0.0、opencv2.2
查看>>
django迁移数据库错误
查看>>
Data truncation: Out of range value for column 'Quality' at row 1
查看>>
字符串处理
查看>>
HtmlUnitDriver 网页内容动态抓取
查看>>
ad logon hour
查看>>
罗马数字与阿拉伯数字转换
查看>>
Eclipse 反编译之 JadClipse
查看>>
距离公式汇总以及Python实现
查看>>
Linux内核态、用户态简介与IntelCPU特权级别--Ring0-3
查看>>
第23月第24天 git命令 .git-credentials git rm --cached git stash clear
查看>>
java SE :标准输入/输出
查看>>
[ JAVA编程 ] double类型计算精度丢失问题及解决方法
查看>>
好玩的-记最近玩的几个经典ipad ios游戏
查看>>
PyQt5--EventSender
查看>>
Sql Server 中由数字转换为指定长度的字符串
查看>>