刚吃完晚饭,闲着没事做就谈一谈自己理解的工厂模式吧:
首先工厂模式分为普通静态工厂模式和抽象工厂模式,我们首先看普通静态工厂模式:
package com.djk.design.factory;
/**
* 普通工厂模式
* @author djk
*
*/
public class FactoryTest3
{
//测试方法
public static void main(String[] args)
{
//得到三角形
//Graphical graphical = GraphicalFactory.getGraphical(Constant.TRIANGLE.getValue());
//得到正方形
Graphical graphical = GraphicalFactory.getGraphical(Constant.SQUARE.getValue());
if(graphical !=null)
{
graphical.sayName();
}else
{
System.out.println("没有对象");
}
}
}
/**
* 图形工厂用于生产图形
* @author djk
*
*/
class GraphicalFactory
{
public static Graphical getGraphical(String name)
{
//根据传进来的参数判断返回哪个对象
if(Constant.TRIANGLE.getValue().equalsIgnoreCase(name))
{
return new Triangle();
}else if (Constant.SQUARE.getValue().equalsIgnoreCase(name))
{
return new Square();
}else
{
try {
throw new Exception();
} catch (Exception e)
{
System.out.println("没有找到对应的对象");
return null;
}
}
}
}
/**
* 图形接口
* @author djk
*
*/
interface Graphical
{
void sayName();
}
/**
* 三角形
* @author djk
*
*/
class Triangle implements Graphical
{
public void sayName()
{
System.out.println("三角形");
}
}
/**
* 正方形
* @author djk
*
*/
class Square implements Graphical
{
public void sayName()
{
System.out.println("正方形");
}
}
/**
* 定义常量类
* @author djk
*
*/
enum Constant
{
TRIANGLE("Triangle"),SQUARE("Square");
private String value;
Constant(String value)
{
this.value =value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
正如上面代码所示的,我现在有一个图形接口Graphical,下面有2个实现类分别是正方形Square和三角形Triangle,有一个生成图形的工厂GraphicalFactory。有了这个图形的工厂以后我们发现当我们要生产一个正方形或三角形对象的时候就不必要在客户端显示的自己去new这个对象,只要调用GraphicalFactory的getGraphical方法并把自己想要得到的图形的名字作为参数传入就OK了,工厂就会返回一个对应的实例,这样减少了在客户端直接new对象,由工厂来处理对象的生成。不过这个普通的静态工厂方法有一个很大的缺点。设计模式中有一个重要的原则就是对扩展开发,对修改闭合,可是这个普工的静态工厂模式没有做到这一点,试想我们后期又加了一种图形的实现类叫圆形,而原工厂的代码是:
public static Graphical getGraphical(String name)
{
//根据传进来的参数判断返回哪个对象
if(Constant.TRIANGLE.getValue().equalsIgnoreCase(name))
{
return new Triangle();
}else if (Constant.SQUARE.getValue().equalsIgnoreCase(name))
{
return new Square();
}else
{
try {
throw new Exception();
} catch (Exception e)
{
System.out.println("没有找到对应的对象");
return null;
}
}
}
如果我们想再加一个圆形让工厂来生产他,那么就要在上面的if语句中多加一个圆形的条件判断,如果多加10个图像的实现类就要多加10个if条件判断这样下去扩展就会显得代码很臃肿,而且违反了设计模式中的对修改闭合,对扩展开放的思想。
接下来将一下抽象工厂模式先看一下对上面代码的一个改进:
package com.djk.design.factory;
/**
* 抽象工厂方法
* @author djk
*
*/
public class FactoryTest4
{
public static void main(String[] args)
{
//生产三角形的工厂
GraphicalFactoryInterFace graphicalFactoryInterFace = new TriangleFactory();
Graphical1 triangle = graphicalFactoryInterFace.getGraphical1();
triangle.sayName();
//生产正方形的工厂
GraphicalFactoryInterFace graphicalFactoryInterFace2 = new SquareFactory();
Graphical1 square = graphicalFactoryInterFace2.getGraphical1();
square.sayName();
}
}
/**
* 抽象工厂定义
* @author djk
*
*/
interface GraphicalFactoryInterFace
{
Graphical1 getGraphical1();
}
/**
* 专门生产三角形的工厂
* @author djk
*
*/
class TriangleFactory implements GraphicalFactoryInterFace
{
public Graphical1 getGraphical1()
{
return new Triangle1();
}
}
/**
* 专门生产正方形的工厂
* @author djk
*
*/
class SquareFactory implements GraphicalFactoryInterFace
{
public Graphical1 getGraphical1()
{
return new Square1();
}
}
/**
* 图形接口
* @author djk
*
*/
interface Graphical1
{
void sayName();
}
/**
* 三角形
* @author djk
*
*/
class Triangle1 implements Graphical1
{
public void sayName()
{
System.out.println("三角形");
}
}
/**
* 正方形
* @author djk
*
*/
class Square1 implements Graphical1
{
public void sayName()
{
System.out.println("正方形");
}
}
这段代码和上面的普通静态工厂模式代码最大的区别之处就是我把工厂也写成了一个抽象的接口,然后具体的工厂来专门生产一种自己能够生产的东西。比如客户端要三角形则就先得到专门生产三角形的工厂然后由这个工厂来专门生产三角形。这样做的好处就是在一定程度上做到了到扩展开放,对修改闭合的设计思想。比如我现在要增加图形的一个实现类圆形,那么我们只要做一个专门生产圆形的工厂即可,这个工厂只要去实现抽象工厂即可,这样就做到了很好的扩展,同时也避免了增加同一种产品时修改以前代码的操作。不过就像刚才所说的这只是在一定程度上做到了对扩展开放,对修改闭合。我们再来设想,此时我们又有一个新的需求,这个需求和以往不同,以往是增加了同一种类的不同对象,现在要求增加另一种类型比如说是Human类型。而我们以前写的工厂接口中只有写了一个抽象方法:
interface GraphicalFactoryInterFace
{
Graphical1 getGraphical1();
}
如果要增加另一种类型那么我们还是要去修改源代码,在源代码的抽象工厂中增加一个生产另一种类型的抽象方法。所以说抽象工厂的在横向(就是同一种类型的扩展)做到了扩展但是对纵向(对不同种类型的扩展)没有做到扩展。但总体上抽象工厂比普通静态工厂进了一步。
我后来想了想怎么修改下抽象工厂方法,让这个抽象工厂在横向和纵向下都能做到扩展。后来我想出了一种方案就是利用泛型接下来看一下我修改的代码:
package com.djk.design.factory;
/**
* 抽象工厂方法
* @author djk
*
*/
public class FactoryTest4
{
public static void main(String[] args)
{
//生产三角形的工厂
FactoryInterFace<Graphical1> graphicalFactoryInterFace = new TriangleFactory();
Graphical1 triangle = graphicalFactoryInterFace.getObject();
triangle.sayName();
//生产正方形的工厂
FactoryInterFace<Graphical1> graphicalFactoryInterFace2 = new SquareFactory();
Graphical1 square = graphicalFactoryInterFace2.getObject();
square.sayName();
//生产人的工厂
FactoryInterFace<Human> graphicalFactoryInterFace3 = new HumanFactory();
Human human = graphicalFactoryInterFace3.getObject();
human.run();
}
}
/**
* 抽象工厂定义
* @author djk
*
*/
interface FactoryInterFace<T>
{
T getObject();
}
/**
* 专门生产三角形的工厂
* @author djk
*
*/
class TriangleFactory implements FactoryInterFace<Graphical1>
{
public Graphical1 getObject()
{
return new Triangle1();
}
}
/**
* 专门生产正方形的工厂
* @author djk
*
*/
class SquareFactory implements FactoryInterFace <Graphical1>
{
public Graphical1 getObject()
{
return new Square1();
}
}
/**
* 图形接口
* @author djk
*
*/
interface Graphical1
{
void sayName();
}
/**
* 增加的一种新的类型
* @author djk
*
*/
interface Animal
{
void run();
}
/**
* 人类是动物的一种
* @author djk
*
*/
class Human implements Animal
{
public void run()
{
System.out.println("人类跑");
}
}
/**
* 人类工厂
* @author djk
*
*/
class HumanFactory implements FactoryInterFace<Human>
{
public Human getObject()
{
return new Human() ;
}
}
/**
* 三角形
* @author djk
*
*/
class Triangle1 implements Graphical1
{
public void sayName()
{
System.out.println("三角形");
}
}
/**
* 正方形
* @author djk
*
*/
class Square1 implements Graphical1
{
public void sayName()
{
System.out.println("正方形");
}
}
这个代码和抽象工厂最大的不同之处就是在抽象工厂上用到了泛型。这个如果后期要在不同种类型上做扩展那么只要把要返回的类型作为泛型写上就OK了。正如上面代码所示:
interface FactoryInterFace<T>
{
T getObject();
}
/**
* 人类工厂
* @author djk
*
*/
class HumanFactory implements FactoryInterFace<Human>
{
public Human getObject()
{
return new Human() ;
}
}
实现这个接口那么就把要返回的类型作为泛型写进去就好了,这样就做到了对不同种类型的扩展。
呵呵 今天看了head first 设计模式中的工厂模式突然想起这里提一下工厂方法和抽象工厂的区别:
二者的区别是:工厂方法只生产一类产品而抽象工厂可以生产多类产品
联系是:当抽象工厂只生产一类产品时其就是工厂方法。。。。
抽象工厂有多个抽象产品,每个抽象产品有多个具体产品,每个抽象工厂的子类可以同时生产多个产品的具体
工厂方法只有一个抽象产品,这个抽象产品有多个具体产品,每个工厂方法的子类只能生产一个产品的具体。。。
呵呵普工静态工厂和抽象工厂就将这么多吧 我讲的不对的地方大家有什么好的意见可以提出来谢谢。。。