合理的模式可以提高代码复用性,可维护性已经灵活性,下面介绍一下设计模式中的工厂模式,简单好用,也是上篇博文——面向接口编程 的更高一层的抽象。
面向接口将规范和实现分离,配合多态,使的代码的复用率提高,减少了代码量,比如说,我们不必为每一个对象写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);
}
}
以上是工厂方法模式。
抽象工厂模式是所有工厂模式中最具一般性的形态,因而也更抽象。会专门用一篇博文做详细的解释。