您的位置:首页 > 其它

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

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下的文本编辑器虽然功能和界面都相同,但是代码实现是不同的,图片处理器也是类似情况,也就是具有了共同的约束条件:操作系统类型,于是我们可以使用抽象工厂模式,产生不同操作系统下的编辑器和图片处理器。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: