这几天正在学习设计模式,看完书,总得写点简单的实例吧:-)
所以呢,从今天开始认真写点简单的纯设计模式实现的 Java 代码,先比较浅显地体会一下设计模式的思想。以便以后在实际项目中正确地使用它。
在这个例子中,ArtTracer 的指责是根据客户的要求绘制各种各样的图形;Shape 接口是提供一些常用的绘图操作,3 个图形类分别实现了它;绘图异常时抛出 BadShapeException。
1. 简单工厂实例UML类图
2. Java实现代码
package cn.edu.ynu.sei.simpleFactory;
/**
* 客户,要求绘图器(<code>ArtTracer</code>)实例绘制需要的图形
*
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public class Client
{
/**
* @param args
*/
public static void main(String[] args)
{
Shape myShape = null;
try
{
myShape = ArtTracer.factory("Circle");
myShape.draw();
myShape = ArtTracer.factory("Square");
myShape.draw();
myShape = ArtTracer.factory("Triangle");
myShape.draw();
myShape.erase();
// ArtTracer.factory("Diamond"); // 将抛出异常
}
catch (BadShapeException bse)
{
bse.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
/**
* 客户,要求绘图器(<code>ArtTracer</code>)实例绘制需要的图形
*
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public class Client
{
/**
* @param args
*/
public static void main(String[] args)
{
Shape myShape = null;
try
{
myShape = ArtTracer.factory("Circle");
myShape.draw();
myShape = ArtTracer.factory("Square");
myShape.draw();
myShape = ArtTracer.factory("Triangle");
myShape.draw();
myShape.erase();
// ArtTracer.factory("Diamond"); // 将抛出异常
}
catch (BadShapeException bse)
{
bse.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
package cn.edu.ynu.sei.simpleFactory;
/**
* 图形绘制器,绘制客户需要的图形
* @author 88250
* @version 1.0.0, 2007-8-12
* @uml.dependency supplier="cn.edu.ynu.sei.simpleFactory.Shape"
* @uml.dependency supplier="cn.edu.ynu.sei.simpleFactory.BadShapeException"
*/
public class ArtTracer
{
/**
* 产生需要的图形实例
* @param which 图形描述
* @return 图形实例
* @throws BadShapeException 产生需要图形异常
*/
public static Shape factory(String which) throws BadShapeException
{
if (which.equalsIgnoreCase("circle"))
{
return new Circle();
}
else if (which.equalsIgnoreCase("square"))
{
return new Square();
}
else if (which.equalsIgnoreCase("triangle"))
{
return new Triangle();
}
else
{
throw new BadShapeException(which);
}
}
}
/**
* 图形绘制器,绘制客户需要的图形
* @author 88250
* @version 1.0.0, 2007-8-12
* @uml.dependency supplier="cn.edu.ynu.sei.simpleFactory.Shape"
* @uml.dependency supplier="cn.edu.ynu.sei.simpleFactory.BadShapeException"
*/
public class ArtTracer
{
/**
* 产生需要的图形实例
* @param which 图形描述
* @return 图形实例
* @throws BadShapeException 产生需要图形异常
*/
public static Shape factory(String which) throws BadShapeException
{
if (which.equalsIgnoreCase("circle"))
{
return new Circle();
}
else if (which.equalsIgnoreCase("square"))
{
return new Square();
}
else if (which.equalsIgnoreCase("triangle"))
{
return new Triangle();
}
else
{
throw new BadShapeException(which);
}
}
}
package cn.edu.ynu.sei.simpleFactory;
/**
* 图形异常<br>
* 例如在不能产生客户需要的图形时将抛出此异常
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public class BadShapeException extends Exception
{
/**
* 异常类版本ID
*/
private static final long serialVersionUID = 4781771889363091309L;
/**
* 构造器
* @param message 异常信息
*/
public BadShapeException(String message)
{
super(message + " has any implementation!");
}
}
/**
* 图形异常<br>
* 例如在不能产生客户需要的图形时将抛出此异常
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public class BadShapeException extends Exception
{
/**
* 异常类版本ID
*/
private static final long serialVersionUID = 4781771889363091309L;
/**
* 构造器
* @param message 异常信息
*/
public BadShapeException(String message)
{
super(message + " has any implementation!");
}
}
package cn.edu.ynu.sei.simpleFactory;
/**
* 广义的图形操作接口
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public interface Shape
{
/**
* 绘制图形
*/
public abstract void draw();
/**
* 擦除图形
*/
public abstract void erase();
}
/**
* 广义的图形操作接口
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public interface Shape
{
/**
* 绘制图形
*/
public abstract void draw();
/**
* 擦除图形
*/
public abstract void erase();
}
package cn.edu.ynu.sei.simpleFactory;
/**
* 圆
*
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public class Circle implements Shape
{
@Override
public void draw()
{
System.out.println("Circle.draw()");
}
@Override
public void erase()
{
System.out.println("Circle.erase()");
}
}
/**
* 圆
*
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public class Circle implements Shape
{
@Override
public void draw()
{
System.out.println("Circle.draw()");
}
@Override
public void erase()
{
System.out.println("Circle.erase()");
}
}
package cn.edu.ynu.sei.simpleFactory;
/**
* 正方形
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public class Square implements Shape
{
@Override
public void draw()
{
System.out.println("Square.draw()");
}
@Override
public void erase()
{
System.out.println("Square.erase()");
}
}
/**
* 正方形
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public class Square implements Shape
{
@Override
public void draw()
{
System.out.println("Square.draw()");
}
@Override
public void erase()
{
System.out.println("Square.erase()");
}
}
package cn.edu.ynu.sei.simpleFactory;
/**
* 三角形
*
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public class Triangle implements Shape
{
@Override
public void draw()
{
System.out.println("Triangle.draw()");
}
@Override
public void erase()
{
System.out.println("Triangle.erase()");
}
}
/**
* 三角形
*
* @author 88250
* @version 1.0.0, 2007-8-12
*/
public class Triangle implements Shape
{
@Override
public void draw()
{
System.out.println("Triangle.draw()");
}
@Override
public void erase()
{
System.out.println("Triangle.erase()");
}
}
3. 总结
简单工厂的核心是工厂类。它决定在什么时候去创建需要的产品,客户端可以免除直接创建产品的重任,
要什么只管对工厂说就可以,这也更符合我们日常的生活逻辑。举个例子,当你需要一把牙刷的时候很
少人会自己去做个自己的牙刷吧?大多人应该都是去牙具店里买XX牌XX型号的牙刷,付钱是当然的了,
但省心哦,嘿嘿。但牙具店老板就费心了,管理那么多不同品种、不同型号的牙刷,一有新品种还要急着
去进货>_<~~~所以,工厂类的责任很重的,如果加入了新的产品就必然要修改它的源代码。
还记得在 面向对象设计原则摘要 里提到的OCP(开-闭原则)吗?这是OOD中相当重要的一个原则,好
的设计都应该做到这一点,那么简单工厂模式是否支持OCP呢?
答案:只能在有限程度上支持。因为OCP要求不能对以“发布”的行为做修改,例如字段或方法,但是可
以进行扩展,可以增加字段或方法。而简单工厂模式中的工厂类不能做到这一点,当加入新的产品类的时候
不得不修改工厂类创建产品方法的逻辑。
尽管如此,简单工厂模式还是相当重要的,因为它是很多设计模式的基础之一,而且有的时候往往简单
的设计可以把工作完成得更出色!
要什么只管对工厂说就可以,这也更符合我们日常的生活逻辑。举个例子,当你需要一把牙刷的时候很
少人会自己去做个自己的牙刷吧?大多人应该都是去牙具店里买XX牌XX型号的牙刷,付钱是当然的了,
但省心哦,嘿嘿。但牙具店老板就费心了,管理那么多不同品种、不同型号的牙刷,一有新品种还要急着
去进货>_<~~~所以,工厂类的责任很重的,如果加入了新的产品就必然要修改它的源代码。
还记得在 面向对象设计原则摘要 里提到的OCP(开-闭原则)吗?这是OOD中相当重要的一个原则,好
的设计都应该做到这一点,那么简单工厂模式是否支持OCP呢?
答案:只能在有限程度上支持。因为OCP要求不能对以“发布”的行为做修改,例如字段或方法,但是可
以进行扩展,可以增加字段或方法。而简单工厂模式中的工厂类不能做到这一点,当加入新的产品类的时候
不得不修改工厂类创建产品方法的逻辑。
尽管如此,简单工厂模式还是相当重要的,因为它是很多设计模式的基础之一,而且有的时候往往简单
的设计可以把工作完成得更出色!