《Java 设计模式》课后习题参考答案
教材:刘伟. Java 设计模式. 北京: 清华大学出版社, 2018.
ISBN: 9787302488316
【说明:本答案供参考,如有意见或建议,请通过电子邮箱 weiliu_china@126.com 与作者
联系!】
第 1 章 设计模式概述
1. D
2. C
3. B
4. 参见教材 P5。
5. 参见教材 P6-P7。
6. 参见教材 P9-P10。
7. 反模式(AntiPatterns)是指那些导致开发出现障碍的负面模式,即在软件开发中普遍存在、
反复出现并会影响到软件成功开发的不良解决方案。反模式是关注于负面解决方案的软件研
究方向,揭示出不成功系统中存在的反模式有利于在成功系统中避免出现这些模式,有助于
降低软件缺陷和项目失败出现的频率。反模式清晰定义了大部分人在软件开发过程中经常会
犯的一些错误,根据视角的不同,可分为开发性反模式、架构性反模式和管理性反模式。
8. JDK 中部分设计模式使用示例列举如下:
创建型模式:
(1) 抽象工厂模式(Abstract Factory)
• java.util.Calendar#getInstance()
• java.util.Arrays#asList()
• java.util.ResourceBundle#getBundle()
• java.net.URL#openConnection()
• java.sql.DriverManager#getConnection()
• java.sql.Connection#createStatement()
• java.sql.Statement#executeQuery()
• java.text.NumberFormat#getInstance()
• java.lang.management.ManagementFactory (所有 getXXX()方法)
• java.nio.charset.Charset#forName()
• javax.xml.parsers.DocumentBuilderFactory#newInstance()
• javax.xml.transform.TransformerFactory#newInstance()
• javax.xml.xpath.XPathFactory#newInstance()
(2) 建造者模式(Builder)
• java.lang.StringBuilder#append()
• java.lang.StringBuffer#append()
• java.nio.ByteBuffer#put() (CharBuffer, ShortBuffer, IntBuffer, LongBuffer, FloatBuffer 和
DoubleBuffer 与之类似)
• javax.swing.GroupLayout.Group#addComponent()
• java.sql.PreparedStatement
1
• java.lang.Appendable 的所有实现类
(3) 工厂方法模式(Factory Method)
• java.lang.Object#toString() (在其子类中可以覆盖该方法)
• java.lang.Class#newInstance()
• java.lang.Integer#valueOf(String) (Boolean, Byte, Character, Short, Long, Float 和
Double 与之类似)
• java.lang.Class#forName()
• java.lang.reflect.Array#newInstance()
• java.lang.reflect.Constructor#newInstance()
(4) 原型模式(Prototype)
• java.lang.Object#clone() (支持浅克隆的类必须实现 java.lang.Cloneable 接口)
(5) 单例模式 (Singleton)
• java.lang.Runtime#getRuntime()
• java.awt.Desktop#getDesktop()
结构型模式:
(1) 适配器模式(Adapter)
• java.util.Arrays#asList()
• javax.swing.JTable(TableModel)
• java.io.InputStreamReader(InputStream)
• java.io.OutputStreamWriter(OutputStream)
• javax.xml.bind.annotation.adapters.XmlAdapter#marshal()
• javax.xml.bind.annotation.adapters.XmlAdapter#unmarshal()
(2) 桥接模式(Bridge)
• AWT (提供了抽象层映射于实际的操作系统)
• JDBC
(3) 组合模式(Composite)
• javax.swing.JComponent#add(Component)
• java.awt.Container#add(Component)
• java.util.Map#putAll(Map)
• java.util.List#addAll(Collection)
• java.util.Set#addAll(Collection)
(4) 装饰模式(Decorator)
• java.io.BufferedInputStream(InputStream)
• java.io.DataInputStream(InputStream)
• java.io.BufferedOutputStream(OutputStream)
• java.util.zip.ZipOutputStream(OutputStream)
• java.util.Collections#checked[List|Map|Set|SortedSet|SortedMap]()
(5) 外观模式(Facade)
• java.lang.Class
• javax.faces.webapp.FacesServlet
(6) 享元模式(Flyweight)
• java.lang.Integer#valueOf(int)
• java.lang.Boolean#valueOf(boolean)
• java.lang.Byte#valueOf(byte)
2
• java.lang.Character#valueOf(char)
(7) 代理模式(Proxy)
• java.lang.reflect.Proxy
• java.rmi.*
行为型模式:
(1) 职责链模式(Chain of Responsibility)
• java.util.logging.Logger#log()
• javax.servlet.Filter#doFilter()
(2) 命令模式(Command)
• java.lang.Runnable
• javax.swing.Action
(3) 解释器模式(Interpreter)
• java.util.Pattern
• java.text.Normalizer
• java.text.Format
• javax.el.ELResolver
(4) 迭代器模式(Iterator)
• java.util.Iterator
• java.util.Enumeration
(5) 中介者模式(Mediator)
• java.util.Timer (所有 scheduleXXX()方法)
• java.util.concurrent.Executor#execute()
• java.util.concurrent.ExecutorService (invokeXXX()和 submit()方法)
• java.util.concurrent.ScheduledExecutorService (所有 scheduleXXX()方法)
• java.lang.reflect.Method#invoke()
(6) 备忘录模式(Memento)
• java.util.Date
• java.io.Serializable
• javax.faces.component.StateHolder
(7) 观察者模式(Observer)
• java.util.Observer/java.util.Observable
• java.util.EventListener (所有子类)
• javax.servlet.http.HttpSessionBindingListener
• javax.servlet.http.HttpSessionAttributeListener
• javax.faces.event.PhaseListener
(8) 状态模式(State)
• java.util.Iterator
• javax.faces.lifecycle.LifeCycle#execute()
(9) 策略模式(Strategy)
• java.util.Comparator#compare()
• javax.servlet.http.HttpServlet
• javax.servlet.Filter#doFilter()
(10) 模板方法模式(Template Method)
• java.io.InputStream, java.io.OutputStream, java.io.Reader 和 java.io.Writer 的所有非抽象
3
方法
• java.util.AbstractList, java.util.AbstractSet 和 java.util.AbstractMap 的所有非抽象方法
• javax.servlet.http.HttpServlet#doXXX()
(11) 访问者模式(Visitor)
• javax.lang.model.element.AnnotationValue 和 AnnotationValueVisitor
• javax.lang.model.element.Element 和 ElementVisitor
• javax.lang.model.type.TypeMirror 和 TypeVisitor
参 见 : http://www.iteye.com/news/18725 和 http://stackoverflow.com/questions/1673841/
examples-of-gof-design-patterns。
第 2 章 面向对象设计原则
1. B A C D D C
2. C
3. D
4. D
5. “封装变化点”可对应“开闭原则”,“对接口进行编程”可对应“依赖倒转原则”,“多使用组合,
而不是继承”可对应“合成复用原则”。
6. 类的粒度需满足单一职责原则,接口的粒度需满足接口隔离原则。
7. 在面向对象设计中,正方形不能作为长方形的子类,具体分析过程如下:
class Rectangle //长方形
{
private double width;
private double height;
public Rectangle(double width,double height)
{
this.width=width;
this.height=height;
}
public double getHeight()
{
return height;
}
public void setHeight(double height)
{
this.height = height;
}
public double getWidth()
{
return width;
}
public void setWidth(double width)
{
this.width = width;
4
public Square(double size)
{
}
super(size,size);
}
}
class Square extends Rectangle //正方形
{
public void setHeight(double height)
{
super.setHeight(height);
super.setWidth(height);
}
public void setWidth(double width)
{
super.setHeight(width);
super.setWidth(width);
}
}
class Client
{
{
public static void main(String args[])
{
}
public static double calculateArea(Rectangle r)
Rectangle r;
r = new Square(0.0);
r.setWidth(5.0);
r.setWidth(10.00);
double area = calculateArea(r);
if(50.00==area)
{
}
else
{
}
return r.getHeight() * r.getWidth();
5
System.out.println("这是长方形或长方形的子类!");
System.out.println("这不是长方形!");
}
}
由代码输出可以得知,我们在客户端代码中使用长方形类来定义正方形对象,将输出“这
不是长方形!”,即将正方形作为长方形的子类,在使用正方形替换长方形之后正方形已经
不再是长方形,接受基类对象的地方接受子类对象时出现问题,违反了里氏代换原则,因此
从面向对象的角度分析,正方形不是长方形的子类,它们都可以作为四边形类的子类。关于
该问题的进一步讨论,大家可以参考其他相关资料,如 Bertrand Meyer 的基于契约设计
(Design By Contract),在长方形的契约(Contract)中,长方形的长和宽是可以独立变化的,但
是正方形破坏了该契约。
8. 重构方案如下所示:
Pen
- color : Color
+ setColor (Color color)
: void
...
Color
SmallPen
MiddlePen
LargePen
Black
Red
在本重构方案中,将笔的大小和颜色设计为两个继承结构,两者可以独立变化,根据依
赖倒转原则,建立一个抽象的关联关系,将颜色对象注入到画笔中;再根据合成复用原则,
画笔在保持原有方法的同时还可以调用颜色类的方法,保持原有性质不变。如果需要增加一
种新的画笔或增加一种新的颜色,只需对应增加一个具体类即可,且客户端可以针对高层类
Pen 和 Color 编程,在运行时再注入具体的子类对象,系统具有良好的可扩展性,满足开闭
原则。(注:本重构方案即为桥接模式)
第 3 章 简单工厂模式
1. C
2. C
3. A
4. 参考类图如下:
Person
+
+
eat ()
sleep ()
...
: void
: void
Nvwa
Man
Woman
Robot
+ makePerson (char arg)
: Person
...
+
+
eat ()
sleep ()
...
: void
: void
+
+
eat ()
sleep ()
...
: void
: void
+
+
eat ()
sleep ()
...
: void
: void
其中,Nvwa 类充当工厂类,其中定义了工厂方法 makePerson(),Person 类充当抽象产
品类,Man、Woman 和 Robot 充当具体产品类。
5. 参考类图如下:
6
UnsupportedShapeException
+ UnsupportedShapeException (
String message)
...
Shape
+
+
draw ()
erase ()
...
: void
: void
ShapeFactory
Circle
Rectangle
Triangle
+ createShape (String type)
: Shape
...
+
+
draw ()
erase ()
...
: void
: void
+
+
draw ()
erase ()
...
: void
: void
+
+
draw ()
erase ()
...
: void
: void
其中,Shape 接口充当抽象产品,其子类 Circle、Rectangle 和 Triangle 等充当具体产品,
ShapeFactory 充当工厂类。
第 4 章 工厂方法模式
1. B
2. D
3. A B
4. 参考类图如下所示:
Client
CarFactory
+ produceCar ()
: Car
...
Car
+ run ()
: void
...
BMWFactory
BenzFactory
BMW
Benz
+ produceCar ()
: Car
+ produceCar ()
: Car
...
...
<>
+ run ()
: void
...
+ run ()
: void
...
<>
其中,Car 充当抽象产品,其子类 BMW 和 Benz 充当具体产品;CarFactory 充当抽象工
厂,其子类 BMWFactory 和 BenzFactory 充当具体工厂。
5. 抽象类/接口 Chart 充当抽象产品,其子类 LineChart 和 BarChart 充当具体产品;抽象类/
接口 ChartFactory 充当抽象工厂,其子类 LineChartFactory 和 BarChartFactory 充当具体工厂。
6. 抽 象 类 / 接 口 Convertor 充 当 抽 象 产 品 , 其 子 类 TXTConvertor 、 DBConvertor 和
ExcelConvertor 充当具体产品 ;抽象类/接口 ConvertorCreator 充当抽 象工厂,其子类
TXTConvertorCreator、DBConvertorCreator 和 ExcelConvertorCreator 充当具体工厂。
参考类图如下:
7
ConvertorCreator
+ getConvertor ()
...
Convertor
+ transform ()
...
DBConvertorCreator
TXTConvertorCreator
DBConvertor
TXTConvertor
+ getConvertor ()
...
+ getConvertor ()
+ transform ()
+ transform ()
...
...
...
7. 参考类图如下:
ImageReaderFactory
+ createImageReader ()
: ImageReader
...
ImageReader
+ readImage ()
: void
...
JpgReaderFactory
+ createImageReader ()
: ImageReader
...
GifReader
JpgReader
+ readImage ()
: void
+ readImage ()
: void
...
<>
...
GifReaderFactory
+ createImageReader ()
...
: ImageReader
其中,ImageReaderFactory 充当抽象工厂,GifReaderFactory 和 JpgReaderFactory 充当具
<>
体工厂,ImageReader 充当抽象产品,GifReader 和 JpgReader 充当具体产品。
第 5 章 抽象工厂模式
1. D
2. D
3. A
4. 参考类图如下所示:
EFactory
+
+
produceTelevision ()
produceAirConditioner ()
...
: Television
: AirConditioner
Television
+ play ()
: void
...
HaierFactory
+
+
produceTelevision ()
produceAirConditioner ()
...
: Television
: AirConditioner
HaierTelevision
TCLTelevision
+ play ()
: void
...
+ play ()
: void
...
TCLFactory
+
+
produceTelevision ()
produceAirConditioner ()
...
: Television
: AirConditioner
AirConditioner
+ changeTemperature ()
: void
...
HairAirConditioner
TCLAirConditioner
+ changeTemperature ()
: void
...
+ changeTemperature ()
: void
...
8