工厂模式---设计模式(二)
2015-09-19 22:07
519 查看
工厂方法模式:
定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
解决的使项目中的实例化问题,一般我们是在某个地方用到某个类就new一个。工厂模式解决的是大量的实例化某些、某种、某批类的对象。
类图:
通用代码:
抽象产品类:
package com.test.Test; public abstract class Product { // 产品类的公共方法 public void method1() { // 业务逻辑处理 } // 抽象方法 public abstract void method2(); }
具体产品类:
具体产品类可以有多个,都继承于抽象产品类。
package com.test.Test; public class ConcreteProduct1 extends Product { public void method2() { // 业务逻辑处理 } }
package com.test.Test; public class ConcreteProduct2 extends Product { public void method2() { // 业务逻辑处理 } }
抽象工厂类:
抽象工厂类负责定义产品对象的产生。
package com.test.Test; public abstract class Creator { /* * 创建一个产品对象,其输入参数类型可以自行设置 * * 通常为String、Enum、Class等,当然也可以为空 */ public abstract Product createProduct(Class<? extends Product> c); }
具体工厂类:
具体如何产生一个产品的对象,是由具体的工厂类实现的。
package com.test.Test; public class ConcreteCreator extends Creator { public Product createProduct(Class<? extends Product> c) { Product product = null; try { product = (Product) Class.forName(c.getName()).newInstance(); } catch (Exception e) { // 异常处理 } return product; } }
场景类:
package com.test.Test; public class Client { public static void main(String[] args) { Creator creator = new ConcreteCreator(); Product product = creator.createProduct(ConcreteProduct1.class); /* * 继续业务处理 */ } }
例子:
抽象产品类:
package com.test.teaAndmilk; /** * 奶茶(抽象产品类) * 2015年9月18日 下午5:19:01 * @author 张耀晖 * */ public abstract class TeaAndMilk { //奶茶类的抽象方法,由具体的子类来实现 public abstract void prepare(); //奶茶类的公共方法 public void doWater(){ System.out.println("加入水。。。"); } public void doMix(){ System.out.println("搅拌均匀。。。"); } public void doCapping(){ System.out.println("封装加盖。。。完成"); } }
具体产品类:
package com.test.teaAndmilk; /** * 绿茶(具体产品类) * 2015年9月18日 下午5:34:17 * @author 张耀晖 * */ public class GreenTea extends TeaAndMilk { @Override public void prepare() { System.out.println("加入绿茶所用的茶叶。。。"); } }
package com.test.teaAndmilk; /** * 珍珠奶茶(具体产品类) * 2015年9月18日 下午5:34:42 * @author 张耀晖 * */ public class GemMilk extends TeaAndMilk { @Override public void prepare() { System.out.println("加入珍珠奶茶需要的材料。。。"); } }
抽象工厂类:
package com.test.Factory; import com.test.teaAndmilk.TeaAndMilk; /** * 抽象奶茶创建工厂(抽象工厂类) * 2015年9月18日 下午5:34:08 * @author 张耀晖 * */ public abstract class FactoryCreator { public abstract <T extends TeaAndMilk> T createTeaAndMilk(Class<T> c); }
具体工厂类:
package com.test.Factory; import com.test.teaAndmilk.TeaAndMilk; /** * 奶茶创建工厂(具体工厂类) * 2015年9月18日 下午5:38:14 * @author 张耀晖 * */ public class TeaAndMilkFactory extends FactoryCreator{ @Override public <T extends TeaAndMilk> T createTeaAndMilk(Class<T> c) { TeaAndMilk teaAndmilk = null; try { teaAndmilk = (TeaAndMilk) Class.forName(c.getName()).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return (T)teaAndmilk; } }
场景类:
package com.test.client; import com.test.Factory.FactoryCreator; import com.test.Factory.TeaAndMilkFactory; import com.test.teaAndmilk.GreenTea; import com.test.teaAndmilk.TeaAndMilk; /** * 奶茶店(场景类) * 2015年9月18日 下午5:46:05 * @author 张耀晖 * */ public class Client { public static void main(String[] args) { FactoryCreator creator = new TeaAndMilkFactory(); //如果顾客需要绿茶 TeaAndMilk teaAndmilk = creator.createTeaAndMilk(GreenTea.class); //具体的业务处理 teaAndmilk.prepare(); teaAndmilk.doWater(); teaAndmilk.doMix(); teaAndmilk.doCapping(); } }
运行结果:
工厂方法模式的优点:
大家应该能够深刻体会到工厂方法模式的好处:如果使用JDBC连接数据库,数据库从MySql切换到Oracle,需要改动地方就是切换一下驱动名称(前提条件是SQL语句是标准语句),其他的都不需要修改,这是工厂方法模式灵活性的一个直接案例。
工厂方法模式的使用场景:
工厂方法模式是new一个对象的替代品,所以在所有需要生成对象的地方都可以使用,但是需要慎重的考虑是否要增加一个工厂类来进行管理,增加代码的复杂度。
工厂方法模式的扩展:
缩小为简单工厂模式:
简单工厂模式:定义一个创建对象的类,由这个类来实例化对象的行为。
上例更改为简单工厂模式:
简单工厂模式中的工厂类:
package com.test.easyFactory; import com.test.teaAndmilk.TeaAndMilk; /** * 奶茶创建工厂(简单工厂模式中的工厂) * 2015年9月18日 下午7:12:51 * @author 张耀晖 * */ public class EasyFactory { public static <T extends TeaAndMilk> T createTeaAndMilk(Class<T> c){ //定义一个生产出的奶茶种类 TeaAndMilk teaAndMilk = null; try { teaAndMilk = (TeaAndMilk)Class.forName(c.getName()).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return (T)teaAndMilk; } }
简单工厂模式中的场景类:
package com.test.easyFactory; import com.test.teaAndmilk.GemMilk; import com.test.teaAndmilk.TeaAndMilk; /** * 奶茶店(场景类) * 2015年9月18日 下午7:21:00 * @author 张耀晖 * */ public class Client { public static void main(String[] args) { TeaAndMilk teaAndMilk = EasyFactory.createTeaAndMilk(GemMilk.class); teaAndMilk.prepare(); teaAndMilk.doWater(); teaAndMilk.doMix(); teaAndMilk.doCapping(); } }
运行结果:
分析与工厂方法模式的不同之处:
将工厂方法模式中的抽象工厂类(FactoryCreator类)去掉了
将具体工厂类(TeaAndMilkFactory类)中的createTeaAndMilk()方法设置为静态方法。简化了类的创建过程。并且去掉了继承抽象类。
因为工厂类发生类变化,所以会导致调用者场景类(Client类)发生类变化。
抽象工厂模式
定义:为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。
通用类图:
通用源码类图:
AbstractProductA和AbstractProductB两个抽象产品类可以有关系,例如共同继承一个抽象类或接口。
通用源码:
抽象产品类:
package com.test.Test; public abstract class AbstractProductA { // 每个产品共有的方法 public void shareMethod() { } // 每个产品相同方法,不同实现 public abstract void doSomething(); }
两个具体的产品实现类
产品A1的实现类:
package com.test.Test; public class ProductA1 extends AbstractProductA { @Override public void doSomething() { System.out.println("产品A1的实现方法"); } }
产品A2的实现类:
package com.test.Test; public class ProductA2 extends AbstractProductA { @Override public void doSomething() { System.out.println("产品A2的实现方法"); } }
产品B与此类似,代码省略了。
抽象工厂类:
抽象工厂类AbstractCreator的职责是定义每个工厂要实现的功能
该抽象工厂类定义了两个产品族的产品创建。
注意: 有N个产品族,在抽象工厂类中就应该有N个创建方法。
package com.test.Test; public abstract class AbstractCreator { // 创建A产品家族 public abstract AbstractProductA createProductA(); // 创建B产品家族 public abstract AbstractProductB createProductB(); }
产品等级1的实现类:
如何创建一个产品,则是有具体的实现类来完成的。
注意: 有M个产品等级就应该有M个实现工厂类,在每个实现工厂中,实现不同产品族的生产任务。
package com.test.Test; public class Creator1 extends AbstractCreator { // 只生产产品等级为1的A产品 public AbstractProductA createProductA() { return new ProductA1(); } // 只生产产品等级为1的B产品 public AbstractProductB createProductB() { return new ProductB1(); } }
产品等级2的实现类:
package com.test.Test; public class Creator2 extends AbstractCreator { // 只生产产品等级为2的A产品 public AbstractProductA createProductA() { return new ProductA2(); } // 只生产产品等级为2的B产品 public AbstractProductB createProductB() { return new ProductB2(); } }
场景类:
package com.test.Test; public class Client { public static void main(String[] args) { // 定义出两个工厂 AbstractCreator creator1 = new Creator1(); AbstractCreator creator2 = new Creator2(); // 产生A1对象 AbstractProductA a1 = creator1.createProductA(); // 产生A2对象 AbstractProductA a2 = creator2.createProductA(); // 产生B1对象 AbstractProductB b1 = creator1.createProductB(); // 产生B2对象 AbstractProductB b2 = creator2.createProductB(); /* * * * * 然后在这里就可以为所欲为了... */ } }
具体的应用实例:
人种接口:
package com.test.human; /** * 人种接口 * 2015年9月18日 下午8:50:17 * @author 张耀晖 * */ public interface Human { // 每个人种都有相应的颜色 public void getColor(); // 人类都会说话 public void talk(); // 每个人都有性别 public void getSex(); }
人种有三个抽象类,负责人种的抽象属性定义:肤色和语言,白色人种、黑色人种、黄色人种
白色人种:
package com.test.human; /** * 白色人种 * 2015年9月18日 下午8:53:22 * @author 张耀晖 * */ public abstract class AbstractWhiteHuman implements Human { @Override //白色人种的皮肤颜色为白色 public void getColor() { System.out.println("白色人种的皮肤颜色为白色!"); } @Override //白色人种讲话 public void talk() { System.out.println("白色人种会说话,一般说的都是单字节!"); } }
黄色人种:
package com.test.human; /** * 黄色人种 * 2015年9月18日 下午8:55:34 * @author 张耀晖 * */ public abstract class AbstractYellowHuman implements Human { @Override //黄色人种的皮肤颜色为黄色 public void getColor() { System.out.println("黄色人种的皮肤颜色为黄色!"); } @Override //黄色人种讲话 public void talk() { System.out.println("黄色人种会讲话,一般说的都是双字节!"); } }
黑色人种:
package com.test.human; /** * 黑色人种 * 2015年9月18日 下午8:53:15 * @author 张耀晖 * */ public abstract class AbstractBlackHuman implements Human { @Override //黑色人种的皮肤颜色为黑色 public void getColor() { System.out.println("黑色人种的皮肤颜色为黑色!"); } @Override //黑色人种讲话 public void talk() { System.out.println("黑色人种会讲话,一般人听不懂!"); } }
每个抽象类都有两个实现类,分别实现公共的最细节、最具体的事物:肤色和语言。具体的实现类肤色性别定义,以黄色女性人种为例。
其他的黑色人种、白色人种的男性和女性的代码与此类似,不再重复编写。
黄色女性人种:
package com.test.human; /** * 黄色女性人种 * 2015年9月18日 下午8:57:53 * @author 张耀晖 * */ public class WomenYellowHuman extends AbstractYellowHuman { @Override //黄人女性 public void getSex() { System.out.println("黄人女性"); } }
黄色男性人种:
package com.test.human; /** * 黄色男性人种 * 2015年9月18日 下午8:59:06 * @author 张耀晖 * */ public class MenYellowHuman extends AbstractYellowHuman { @Override //黄人男性 public void getSex() { System.out.println("黄人男性"); } }
八卦炉定义:
package com.test.factory; import com.test.human.Human; /** * 八卦炉定义 * 2015年9月18日 下午9:03:35 * @author 张耀晖 * */ public interface HumanFactory { //制造一个黄色人种 public Human createYellowHuman(); //制造一个黑色人种 public Human createBlackHuman(); //制造一个白色人种 public Human createWhiteHuman(); }
具体的八卦炉:
生产女性的八卦炉:
package com.test.factory; import com.test.human.Human; import com.test.human.WomenBlackHuman; import com.test.human.WomenWhiteHuman; import com.test.human.WomenYellowHuman; /** * 生产女性的八卦炉 * 2015年9月18日 下午9:05:53 * @author 张耀晖 * */ public class WomenFactory implements HumanFactory { @Override //生产出黄人女性 public Human createYellowHuman() { return new WomenYellowHuman(); } @Override //生产出黑人女性 public Human createBlackHuman() { return new WomenBlackHuman(); } @Override //生产出白人女性 public Human createWhiteHuman() { return new WomenWhiteHuman(); } }
生产男性的八卦炉:
package com.test.factory; import com.test.human.Human; import com.test.human.MenBlackHuman; import com.test.human.MenWhiteHuman; import com.test.human.MenYellowHuman; /** * 生产男性的八卦炉 * 2015年9月18日 下午9:11:20 * @author 张耀晖 * */ public class MenFactory implements HumanFactory { @Override //生产出黄人男性 public Human createYellowHuman() { return new MenYellowHuman(); } @Override //生产出黑人男性 public Human createBlackHuman() { return new MenBlackHuman(); } @Override //生产出白人男性 public Human createWhiteHuman() { return new MenWhiteHuman(); } }
女娲类(场景类):
package com.test.Client; import com.test.factory.HumanFactory; import com.test.factory.MenFactory; import com.test.factory.WomenFactory; import com.test.human.Human; /** * 女娲造人 * 2015年9月18日 下午9:18:56 * @author 张耀晖 * */ public class NvWa { public static void main(String[] args) { //第一条生产线,男性生产线 HumanFactory menFactory = new MenFactory(); //第二条生产线,女性生产线 HumanFactory womenFactory = new WomenFactory(); //生产线建立完毕,开始生产人 Human menYellowHuman = menFactory.createYellowHuman(); Human womenYellowHuman = womenFactory.createYellowHuman(); menYellowHuman.getColor(); menYellowHuman.talk(); menYellowHuman.getSex(); womenYellowHuman.getColor(); womenYellowHuman.talk(); womenYellowHuman.getSex(); //下面继续创建黑人和白人的男性和女性。。。。。。 } }
运行结果:
抽象工厂模式的使用场景
抽象工厂模式的使用场景定义非常简单:一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式,什么意思呢?例如一个文本编辑器和一个图片处理器,都是软件实体,但是*nix下的文本编辑器和WINDOWS下的文本编辑器虽然功能和界面都相同,但是代码实现是不同的,图片处理器也是类似情况,也就是具有了共同的约束条件:操作系统类型,于是我们可以使用抽象工厂模式,产生不同操作系统下的编辑器和图片处理器。
相关文章推荐
- 你所不知道的layout_weight
- 随感
- 数据结构实践——括号的匹配(栈)
- Linux:目录&文件基本操作
- 对git的认识
- YoMail,Gmail死忠粉的福音——直接收发Gmail邮件
- test5.12
- sizeof()和strlen()不得不说的故事
- 2.1-squid正向代理
- nodejs+express+mongodb简单的例子
- 百度测试开发9/16/2015
- 我的2015
- Fragment----静态创建碎片
- 2016京东在线笔试(编程题之一)
- netbeans中表格使用
- 编程练习(1)
- Grub
- hdu 5464(01背包)
- sin(x)的实现
- HDOJ 1846 Brave Game(巴什博奕)