博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式读完总结(2)工厂模式
阅读量:4342 次
发布时间:2019-06-07

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

1.问 : 很多时候通过反射机制就可以很灵活地创建对象,为毛还要工厂?微笑

将对象的创建和使用分开,单一职责两个类A和B之间的关系应该仅仅是A创建B或是A使用B,而不能两种关系都有

与一个对象相关的职责通常有三类:对象本身所具有的职责、创建对象的职责和使用对象的职责

   在语言中,我们通常有以下几种创建对象的方式:

       (1) 使用new关键字直接创建对象;  

       (2) 通过反射机制创建对象;

       (3) 通过clone()方法创建对象;

       (4) 通过工厂类创建对象。

new 灵活性不好,不符合开闭原则。

反射 不太安全,而且性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。在业务代码中唯一合理(直接)使用反射的场景是通过AOP。除此之外,你最好远离反射这一特性。

将对象的创建和使用分离还有一个好处:防止用来实例化一个类的数据和代码在多个类中到处都是,可以将有关创建的知识搬移到一个工厂类中

一个类可能拥有多个构造函数,构造函数名字都与类名相同,将对象的创建过程封装在工厂类中,我们可以提供一系列名字完全不同的工厂方法,每一个工厂方法对应一个构造函数,客户端可以以一种更加可读、易懂的方式来创建对象。

 

2.简单工厂模式:一个工厂类 来创建所有的产品对象

abstract class Product {
  //所有产品类的公共业务方法   public void methodSame() {
  //公共方法的实现   }   //声明抽象业务方法   public abstract void methodDiff(); }

class ConcreteProduct extends Product {

  //实现业务方法
  public void methodDiff() {
    //业务方法的实现
  }
}

class Factory {  //静态工厂方法  也可用反射机制实现    public static Product getProduct(String arg) {        Product product = null;        if (arg.equalsIgnoreCase("A")) {            product = new ConcreteProductA();            //初始化设置product        }        else if (arg.equalsIgnoreCase("B")) {            product = new ConcreteProductB();            //初始化设置product        }        return product;    }}

class Client {

  public static void main(String args[]) {
    Product product;
    product = Factory.getProduct("A"); //通过工厂类创建产品对象
    product.methodSame();
    product.methodDiff();
  }
}

 

 

我们可以将静态工厂方法的参数存储在XML或properties格式的配置文件中,如下config.xml所

示:
<?xml version="1.0"?>
<config>
<chartType>histogram</chartType>
</config>
再通过一个工具类XMLUtil来读取配置文件中的字符串参数,XMLUtil类的代码如下所示:

import javax.xml.parsers.*;

import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
public class XMLUtil {
//该方法用于从XML配置文件中提取图表类型,并返回类型名
public static String getChartType() {
try {
//创建文档对象
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File("config.xml"));
//获取包含图表类型的文本节点
NodeList nl = doc.getElementsByTagName("chartType");
Node classNode = nl.item(0).getFirstChild();
String chartType = classNode.getNodeValue().trim();
return chartType;
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
}

有时候,为了简化简单工厂模式,我们可以将抽象产品类和工厂类合并,将静态工厂方法移至抽象产品类中。

缺点:

(1) 工厂类过于庞大,包含了大量的if…else…代码,导致维护和测试难度增大;

(2) 系统扩展不灵活,如果增加新类型的产品类,必须修改静态工厂方法的业务逻辑,违反了“开闭原则”。

 适用场景

(1) 工厂类负责创建的对象比较少,工厂方法中的业务逻辑不会太过复杂。
(2) 客户端只知道传入工厂类的参数,对于如何创建对象并不关心。

 结论:对象种类比较少的时候用。

 

3.工厂方法:针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级结构

 

 

 

 

 

 

//*****引入抽象工厂 interface Factory {  public Product factoryMethod();}wclass ConcreteFactory implements Factory {  public Product factoryMethod() {    return new ConcreteProduct();}Factory factory;factory = new ConcreteFactory(); //可通过配置文件实现Product product;product = factory.factoryMethod();}

 

 缺点:类太多

 

4.抽象工厂模式:在抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品,这些产品构成了一个产品族,抽象工厂模式结构如图5所示:

abstract class AbstractFactory {    public abstract AbstractProductA createProductA(); //工厂方法一    public abstract AbstractProductB createProductB(); //工厂方法二  ……  }class ConcreteFactory1 extends AbstractFactory {      //工厂方法一    public AbstractProductA createProductA() {        return new ConcreteProductA1();    }    //工厂方法二    public AbstractProductB createProductB() {        return new ConcreteProductB1();    }  ……  }

 

 

 

 

           按钮       文本框    组合框

绿色

蓝色

//界面皮肤工厂接口:抽象工厂  interface SkinFactory {      public Button createButton();      public TextField createTextField();      public ComboBox createComboBox();  }  //Spring皮肤工厂:具体工厂  class SpringSkinFactory implements SkinFactory {      public Button createButton() {          return new SpringButton();      }      public TextField createTextField() {          return new SpringTextField();      }      public ComboBox createComboBox() {          return new SpringComboBox();      }  }  //Summer皮肤工厂:具体工厂  class SummerSkinFactory implements SkinFactory {      public Button createButton() {          return new SummerButton();      }      public TextField createTextField() {          return new SummerTextField();      }      public ComboBox createComboBox() {          return new SummerComboBox();      }  }

 

一般情况下,一个具体工厂中只有一个或者一组重载的工厂方法。但是有时候我们希望一个工厂可以提供多个产品对象,而不是单一的产品对象,如一个电器工厂,它可以生产电视机、电冰箱、空调等多种电器。

抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。

总结:增加产品族支持开闭原则,增加产品等级,则不支持。(产品等级:父类与多个子类实现)开闭原则倾斜性。

 

 

适用场景

 

在以下情况下可以考虑使用抽象工厂模式:

 

(1) 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是很重要的,用户无须关心对象的创建过程,将对象的创建和使用解耦。

 

(2) 系统中有多于一个的产品族,而每次只使用其中某一产品族。可以通过配置文件等方式来使得用户可以动态改变产品族,也可以很方便地增加新的产品族。

 

(3) 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。同一个产品族中的产品可以是没有任何关系的对象,但是它们都具有一些共同的约束,如同一操作系统下的按钮和文本框,按钮与文本框之间没有直接关系,但它们都是属于某一操作系统的,此时具有一个共同的约束条件:操作系统的类型。

 

(4) 产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。

 

 

转载于:https://www.cnblogs.com/wuer888/p/6678235.html

你可能感兴趣的文章
Sybase IQ导出文件的几种方式
查看>>
案例:手动输入一个字符串,打散放进一个列表,小写字母反序 大写字母保持不变...
查看>>
linux 系统下 tar 的压缩与解压缩命令
查看>>
阿里负载均衡,配置中间证书问题(在starcom申请免费DV ssl)
查看>>
转:How to force a wordbreaker to be used in Sharepoint Search
查看>>
MySQL存储过程定时任务
查看>>
Python中and(逻辑与)计算法则
查看>>
POJ 3267 The Cow Lexicon(动态规划)
查看>>
设计原理+设计模式
查看>>
tomcat 7服务器跨域问题解决
查看>>
前台实现ajax 需注意的地方
查看>>
Jenkins安装配置
查看>>
个人工作总结05(第二阶段)
查看>>
Java clone() 浅拷贝 深拷贝
查看>>
深入理解Java虚拟机&运行时数据区
查看>>
02-环境搭建
查看>>
spring第二冲刺阶段第七天
查看>>
搜索框键盘抬起事件2
查看>>
阿里百川SDK初始化失败 错误码是203
查看>>
透析Java本质-谁创建了对象,this是什么
查看>>