合理的模式可以提高代码复用性,可维护性已经灵活性,下面介绍一下设计模式中的工厂模式,简单好用,也是上篇博文——面向接口编程 的更高一层的抽象。
面向接口将规范和实现分离,配合多态,使的代码的复用率提高,减少了代码量,比如说,我们不必为每一个对象写doEverything方法了,但是,当50个类中都需要new出person的话,我们还要在50个类中分别new出50个person,这似乎是必须的,但是当我们突然发现不应该new person,而应该new fox的时候,我们就需要到50个类中分别修改代码(这不是开闭原则..),不开心啊。。。。如果我们可以在将new 对象的动作放在一个统一的地方,只要在这个地方改一下,就可以将全局的person变成fox,岂不是大快人心。工厂来了,救星来了——更高一层的抽象。
工厂顾名思义,生产货品的地方,java中肯定是生产对象的地方,这里我们可以假设一个厂房有4个button,A,B,C,D分别对应person、cat、dog、fox,当我们发现person需要换成fox,简单,别按按钮A了,按下按钮D,fox就源源不断从流水线上出来了。是的,我们不再自己动手new对象了,而将这个动作托管给了工厂,当我们需要要某个对象的时候,只需要从工厂取就好了。
进入正题:
工厂模式分为两类:
1.工厂方法模式;(简单工厂模式是工厂方法模式的一个特例)
2.抽象工厂模式
先从最简单的简单工厂模式开始,先将该模式的几个角色定位一下:
1.工厂类角色:是具体产品类角色的构造者;(工厂模式,肯定要有工厂啦)
2.抽象产品角色:被工厂创建的对象;(之所以需要抽象产品,原因在面向接口编程中已经说过了)
3.具体产品角色:调用工厂类产生实例,并利用多态进行相应工作。(有抽象,就必须要有具体的实现类)
4.消费者角色:请求工厂生产实例(有生产就有买卖)
用上篇博文中(http://huntfor.iteye.com/admin/blogs/2024611)的例子:
package factoryPattern; import Gof.Runable; public class FactoryPattern { private static void doEverything(Runable runable) { System.out.println("now I am ready to run...."); runable.run(); System.out.println("I am tired and wanna walk for a while..."); runable.walk(); System.out.println("I am totally tired wanna stop...."); runable.stop(); } public static void main(String[] args) { // 将new 对象的工作托管给工厂,工厂实现对对象的统一管理 Runable product = Factory.getByType('A'); doEverything(product); } } class Factory { // 这里当然可以用非静态方法 public static Runable getByType(char type) { if (type == 'A') { return new Person(); } else if (type == 'B') { return new Cat(); } else if (type == 'C') { return new Dog(); } else if (type == 'D') { return new Fox(); } else { return null; } } } class Person implements Runable { @Override public void run() { System.out.println("people run...."); } @Override public void walk() { System.out.println("people walk...."); } @Override public void stop() { System.out.println("people stop...."); } ....下面的几个都一样 }
这样,就对实例对象的产生有统一到了一个接口上(不再是狭义的interface),消费者直接与工厂这层接口交互,将new对象的过程又一次进行了封装。
工厂方法模式是简单工厂模式的衍生,并且解决了很多简单工厂模式存在的问题:
开闭原则要就我们对外可扩展,这里就暴露了简单工厂模式的局限性。现实生活中,一个工厂往往工作单一,比如说可口可乐公司只生产可乐,你可以生产各种汽水,比如雪碧,芬达,酷儿,醒目等等,但是你总不能生产空调吧。夏天即需要空调又需要可乐,怎么办?很简单啊,再建一个空调厂就可以了。问题又来了,这样的话,岂不是又要到处new 空调厂和可乐厂了?如果有必要,我们可以对这两个工厂再做一次工厂模式,建造一个生产工厂的工厂。
插句嘴:工厂方法模式是典型的模板方法模式的应用。后面再讲
工厂方法模式的框架:
很简单,对每种产品建造响应的工厂。
下面简单实现一下:
产品接口:
package factoryPattern; public interface IProduct { void function(); } abstract class Cola implements IProduct{ @Override public void function() { System.out.println("用於解渴"); } public abstract void getMyBrand(); } class CocoCola extends Cola{ @Override public void getMyBrand() { System.out.println("我是可口可乐"); } } class Sprite extends Cola{ @Override public void getMyBrand() { System.out.println("我是雪碧"); } } abstract class AirCondition implements IProduct{ @Override public void function() { System.out.println("用于降温"); } public abstract void getMyPower(); } class Galanz extends AirCondition{ @Override public void getMyPower() { System.out.println("我的功率是1P"); } } class Midea extends AirCondition{ @Override public void getMyPower() { System.out.println("我的功率是1.5P"); } }
工厂接口:
public interface INormalFactory { IProduct produce(String type)throws Exception; }
工厂实现类:
package factoryPattern; public class ColaFactory implements INormalFactory { @Override public IProduct produce(String type) throws Exception { if(type == "A"){ return new CocoCola(); } else if(type == "B"){ return new Sprite(); }else{ throw new Exception("your type is not fund"); } } } class AirConditionFactory implements INormalFactory { @Override public IProduct produce(String type)throws Exception { if(type =="A"){ return new Galanz(); }else if(type == "B"){ return new Midea(); }else{ throw new Exception("your type is not fund"); } } }
消费者角色:(我画蛇添足的加了一点反射以及抽象类,如果不是很清楚的,可以先简单看一下反射)
package factoryPattern; public class NormalFactoryTest { static void getDetail(IProduct product) throws InstantiationException, IllegalAccessException{ product.function(); if(product instanceof Cola){ if(product.getClass().newInstance() instanceof Cola){ ((Cola)product).getMyBrand(); } }else if(product instanceof AirCondition){ if(product.getClass().newInstance() instanceof Galanz){ ((Galanz)product).getMyPower(); }else if(product.getClass().newInstance() instanceof Midea){ ((Midea)product).getMyPower(); } } } public static void main(String[] args) throws Exception { INormalFactory colaFactory = new ColaFactory(); INormalFactory airContidionFactory = new AirConditionFactory(); IProduct cocoCola = colaFactory.produce("A"); IProduct sprite = colaFactory.produce("B"); IProduct glanze = airContidionFactory.produce("A"); IProduct midea = airContidionFactory.produce("B"); getDetail(cocoCola); getDetail(sprite); getDetail(glanze); getDetail(midea); } }
以上是工厂方法模式。
抽象工厂模式是所有工厂模式中最具一般性的形态,因而也更抽象。会专门用一篇博文做详细的解释。
相关推荐
设计模式——抽象工厂模式源码,设计模式——抽象工厂模式源码
这个是http://blog.csdn.net/dawanganban/article/details/9877593博客中java设计模式的源代码。下载前请先看《设计模式——工厂方法模式》一文。
这个是http://blog.csdn.net/dawanganban/article/details/9884681博客中java设计模式的源代码。下载前请先看《设计模式——工厂模式在开发中的应用》一文。
经典的设计模式————简单工厂模式,里面有实验文档和实验源代码还有课件助于你的学习
这个是http://blog.csdn.net/dawanganban/article/details/9875873博客中java设计模式的源代码。下载前请先看《设计模式——简单工厂》一文。
vs2010实现的软件设计模式——抽象工厂,是软件工程专业学生专业技能之一
Android之大话设计模式——:抽象工厂模式借鉴.pdf
写博客上传的代码:blog http://blog.csdn.net/t1234xy4/article/details/52424048
设计模式C#描述之——简单工厂模式,让你学习C#的一种设计模式
C#设计模式(23种设计模式) 1. 单件模式(Singleton Pattern) 2. 抽象工厂(Abstract Factory) 3. 建造者模式(Builder) 4. 工厂方法模式(Factory Method) 5. 原型模式(Prototype) 结构型: 6. 适配器...
工厂方法模式之所以可以解决简单工厂的模式,是因为它的实现把具体产品的创建推迟到子类中,此 时工厂类不再负责所有产品的创建,而...下面看下工厂模式 的具体实现代码(这里还是以简单工厂模式中点菜的例子来实现):
Android之大话设计模式——:抽象工厂模式参考.pdf
主要介绍了Java设计模式——工厂设计模式详解,具有一定参考价值,需要的朋友可以了解下。
NULL 博文链接:https://maidoudao.iteye.com/blog/1328618
NULL 博文链接:https://quicker.iteye.com/blog/607944
工厂模式: – 实现了创建者和调用者的分离。 – 详细分类: 简单工厂模式 工厂方法模式 抽象工厂模式 面向对象设计的基本原则: OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改...
java23种设计模式 工厂模式 ,抽象工厂,建造者模式,单态模式,原型模式
简介 设计模式是为了解决一些出现的问题设计的解决方案。是长时间经验的总结,是根据...工厂模式 在类中实现一个接口创建指定对象,使一个类的实例化延迟到了子类。简单来说把类的创建都封装起来,只需要调用一个子类
NULL 博文链接:https://quicker.iteye.com/blog/608844
1.1 什么是设计模式 2 1.2 Smalltalk MVC中的设计模式 3 1.3 描述设计模式 4 1.4 设计模式的编目 5 1.5 组织编目 7 1.6 设计模式怎样解决设计问题 8 1.6.1 寻找合适的对象 8 1.6.2 决定对象的粒度 9 1.6.3 指定对象...