工厂模式---设计模式(二)

工厂方法模式:

定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

解决的使项目中的实例化问题,一般我们是在某个地方用到某个类就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();
    }

}

运行结果:
这里写图片描述

分析与工厂方法模式的不同之处:

  1. 将工厂方法模式中的抽象工厂类(FactoryCreator类)去掉了
  2. 将具体工厂类(TeaAndMilkFactory类)中的createTeaAndMilk()方法设置为静态方法。简化了类的创建过程。并且去掉了继承抽象类。
  3. 因为工厂类发生类变化,所以会导致调用者场景类(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下的文本编辑器虽然功能和界面都相同,但是代码实现是不同的,图片处理器也是类似情况,也就是具有了共同的约束条件:操作系统类型,于是我们可以使用抽象工厂模式,产生不同操作系统下的编辑器和图片处理器。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值