大话设计模式(八)抽象工厂模式进化
来源:互联网 发布:软件开发环境 编辑:程序博客网 时间:2024/04/26 00:00
大话设计模式(八)抽象工厂模式进化
前情回顾
在博文《大话设计模式(七)抽象工厂模式》中,我们了解了抽象工厂设计模式。在讲解反射机制时,我们提到反射机制实现了程序由编译时到运行时变量的指定。我们的设计不能防止需求的更改,那么我们的理想就是让变动变得最小。结合前面的代码讲解,当我们需要增加产品C时,那么我们就需要增加3个类。并修改3个类。
//抽象产品C,定义了产品的公共方法,产品A、B和C属于一个产品族 interface ProductC { public void method1(); public void method2();}// 等级为1的具体产品Cclass ConcreateProductC1 implements ProductC { @Override public void method1() { System.out.println("等级为1的产品C的method1()"); } @Override public void method2() { System.out.println("等级为1的产品C的method2()"); }}// 等级为2的具体产品Cclass ConcreateProductC2 implements ProductC { @Override public void method1() { System.out.println("等级为2的产品C的method1()"); } @Override public void method2() { System.out.println("等级为2的产品C的method2()"); }}// 修改//抽象工厂,定义了生产族产品的方法; interface AbstractFactory_ { public ProductA factoryA(); public ProductB factoryB(); public ProductC factoryC(); }// 具体工厂(生产等级为1的族产品)class ConcreateFactory1 implements AbstractFactory_ { // 生产等级为1的产品A @Override public ProductA factoryA() { return new ConcreateProductA1(); } // 生产等级为1的产品B @Override public ProductB factoryB() { return new ConcreateProductB1(); } // 生产等级为1的产品C @Override public ProductC factoryC() { return new ConcreateProductC1(); }} //具体工厂(生产等级为2的族产品)class ConcreateFactory2 implements AbstractFactory_ { // 生产等级为2的产品A @Override public ProductA factoryA() { return new ConcreateProductA2(); } // 生产等级为2的产品B @Override public ProductB factoryB() { return new ConcreateProductB2(); } // 生产等级为2的产品C @Override public ProductC factoryC() { return new ConcreateProductC2(); }}
优化之简单工厂模式
可见,对于程序的扩展性、灵活性提出了严峻的挑战。为此,我们可以使用简单工厂模式来进行重新设计。
package cn.edu.ujn.designpattern;class ProductAccess{// private static String name = "A1"; private static String name = "A2"; // private static String name = "B1";// private static String name = "B2"; // private static String name = "C"; public static AbstractFactory_ creatProduct(){ AbstractFactory_ result = null; switch (name) { case "A1": result = new ConcreateFactory1(); ProductA productA1 = new ConcreateProductA1(); productA1.method1(); break; case "A2": result = new ConcreateFactory1(); ProductA productA2 = new ConcreateProductA2(); productA2.method2(); break; case "B1": ProductB productB1 = new ConcreateProductB1(); productB1.method1(); break; case "B2": ProductB productB2 = new ConcreateProductB2(); productB2.method2(); break;/* case "C1": ProductC productC1 = new ConcreateProductC1(); productC1.method1(); break; */ } return result; }}public class AbstractFactory_Modified { public static void main(String[] args) { ProductAccess.creatProduct(); }}
我们通过利用简单工厂模式,抛弃了抽象工厂AbstractFactory_、抽象角色ProductA、ProductB、ProductC等若干个工厂类,取而代之的是ProductAccess类,由于事先设置了name的值(A1、A2、B1、B2、C1、C2),所以简单工厂的方法都不需要输入参数,这样在客户端就只需要ProductAccess.creatProduct();来生成具体的产品实例,客户端没有出现任何一个A1、A2、B1、B2、C1、C2的字样,达到了解耦的目的。
优化之反射机制
但是,问题依旧存在。如果我们需要增加产品D获取,这样就需要在ProductAccess类中增加case了,同单例模式存在一样的问题:违反了OCP原则。为此,我们可以通过使用反射+单例模式实现。
package cn.edu.ujn.designpattern;class Fruit_Factory { /** * 获取实例 * @param productName 实体 * @return */ public static Fruit createAnimal(String fullName){ try { // 通过反射获取实例,通过给定类的字符串名称获取该类,类的全名 Class clazz = Class.forName(fullName); try { return (Fruit) clazz.newInstance(); } catch (InstantiationException e) { throw new RuntimeException("实例化异常!",e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } catch (ClassNotFoundException e) { throw new RuntimeException("这个实体类不存在!",e); } }}public class SimpleFactory_Reflection { public static void main(String[] args) { //测试 String className = "cn.edu.ujn.designpattern.Apple"; Fruit apple = (Fruit) Fruit_Factory.createAnimal(className); apple.grow(); }}
优化之配置文件+反射
这么写的话还是有点缺憾,因为在更换生成对象的时候,还是需要去改程序(改这个className的值)重编译,如果可以不改程序,那才是真正的符合OCP。为此,我们可以利用配置文件来解决更改的问题。
package cn.edu.ujn.designpattern;import java.io.IOException;import java.io.InputStream;import java.util.Properties;class Fruit_Factory { /** * 获取实例 * @param productName 实体 * @return */ public static Fruit createFruit(){ Properties pro = new Properties(); InputStream ins; ins = Fruit.class.getResourceAsStream("factory.properties"); try { pro.load(ins); } catch (IOException e) { e.printStackTrace(); } finally{ try { ins.close(); } catch (IOException e) { e.printStackTrace(); } } String implClassStr = pro.get("implClass").toString(); try { // 通过反射获取实例,通过给定类的字符串名称获取该类,类的全名 Class clazz = Class.forName(implClassStr); try { return (Fruit) clazz.newInstance(); } catch (InstantiationException e) { throw new RuntimeException("实例化异常!",e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } catch (ClassNotFoundException e) { throw new RuntimeException("这个实体类不存在!",e); } }}public class SimpleFactory_Reflection { public static void main(String[] args) { //测试 String className = "cn.edu.ujn.designpattern.Apple"; Fruit apple = (Fruit) Fruit_Factory.createFruit(); apple.grow(); }}
可添加一个配置文件factory.properties,内容如下:
implClass=cn.edu.ujn.designpattern.Apple
从这个角度上看,所有在使用简单工厂的地方,都可以考虑使用反射技术去除switch或if,解除分支判断带来的耦合,使之更加容易维护和扩展。
- 大话设计模式(八)抽象工厂模式进化
- 大话设计模式 抽象工厂
- 大话设计模式-抽象工厂模式
- 大话设计模式_抽象工厂模式
- 大话设计模式之抽象工厂模式
- 《大话设计模式》 -- 14.抽象工厂模式
- 大话设计模式之抽象工厂模式
- 大话设计模式-抽象工厂模式
- 大话设计模式:抽象工厂模式
- 大话设计模式15----抽象工厂模式
- 大话设计模式(七)抽象工厂模式
- 大话设计模式-抽象工厂模式
- 大话设计模式-抽象工厂模式-简单工厂模式结合
- 大话设计之抽象工厂模式
- linkin大话设计模式--抽象工厂
- 大话设计模式读书笔记之抽象工厂
- 设计模式--抽象工厂模式(八)
- 大话设计模式-----(五)观察者模式、抽象工厂模式
- 优先队列的链表实现
- easyUI中class="easyui-combobox"默认选值
- Cannot fetch index base URL https://pypi.python.org/simple/
- POJ3693 Maximum repetition substring 后缀数组
- 几种常见的排序算法(C++)
- 大话设计模式(八)抽象工厂模式进化
- servlet学习总结(二)—图片下载和读取属性文件
- UIApplicationLaunchOptionsRemoteNotificationKey
- 用rem来做响应式开发
- 知识点二:文件的输入和输出
- hdu 5074
- Java之正则表达式
- C 自定义输入函数
- 基于spark的大数据提取校验框架