设计模式中的创造型模式,包括单例模式、工厂模式、抽象工厂模式、生成器模式、原型模式,本文主要用简单的实例介绍这几种设计模式。
· 单例模式 - 美国只有一个总统 原文 Singleton – Only one president in America
· 工厂模式 - 一个生产人类的工厂 原文 Factory – A factory that produces human
· 抽象工厂模式 - 一个生产CPU的抽象工厂 原文 Abstract Factory – An abstract factory to produce CPUs
· 生成器模式 - 生成一杯饮料 原文 Builder – Build a drink
· 原型模式 - 创建很多相似的对象 原文 Prototype – Create a lot of similar objects
翻译自 Java Design Pattern: Singleton
单例模式在Java中最常用的模式之一。它能阻止外部的实例化和修改,从而控制创建的对象的数量。这个概念可以应用到只允许一个对象存在时的操作,或者限制在一定数量的对象的操作,如:
1. 私有构造函数 - 没有其他类可以实例化一个新的对象。
2. 私有引用 - 没有外部修改。
3. 公共静态方法是唯一可以得到对象引用的地方。
单例模式的故事
下面是一个简单的使用情况。一个国家只能有一个总统(这是正常的情况)。所以每当我们要引用总统对象,只需要通过AmericaPresident返回,其中的getPresident()方法将确保始终只有一个总统创建。否则,它就不会符合正常情况。
类图
Java 代码
package com.programcreek.designpatterns.singleton;
public class AmericaPresident {
private AmericaPresident() { }
private static AmericaPresident thePresident;
public static AmericaPresident getPresident(){
if(thePresident == null)
thePresident = new AmericaPresident();
return thePresident;
}
}
单例模式在Java标准类库中的使用
java.lang.Runtime#getRuntime()是Java标准库中的一种常用方法。 getRunTime()返回与当前Java应用程序的运行时对象。下面是一个简单的使用getRunTime()的例子,在Windows系统上读取网页。
Process p = Runtime.getRuntime().exec(
"C:/windows/system32/ping.exe programcreek.com");
//get process input stream and put it to buffered reader
BufferedReader input = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line;
while ((line = input.readLine()) != null) {
System.out.println(line);
}
input.close();
输出:
Pinging programcreek.com [198.71.49.96] with 32 bytes of data: Reply from 198.71.49.96: bytes=32 time=53ms TTL=47 Reply from 198.71.49.96: bytes=32 time=53ms TTL=47 Reply from 198.71.49.96: bytes=32 time=52ms TTL=47 Reply from 198.71.49.96: bytes=32 time=53ms TTL=47 Ping statistics for 198.71.49.96: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 52ms, Maximum = 53ms, Average = 52ms
翻译自 Java Design Pattern: Factory
1、工厂模式的故事
工厂模式用来根据不同的参数创建对象。下面的例子是用工厂创造人类。如果我们问工厂要一个男孩,则工厂会产生一个男孩,如果我们问工厂要一个女孩,工厂将产生一个女孩。根据不同的参数,工厂会生产不同的东西。
2、工厂模式的类图
3、工厂模式的Java代码
interface Human {
public void Talk();
public void Walk();
}
class Boy implements Human{
@Override
public void Talk() {
System.out.println("Boy is talking...");
}
@Override
public void Walk() {
System.out.println("Boy is walking...");
}
}
class Girl implements Human{
@Override
public void Talk() {
System.out.println("Girl is talking...");
}
@Override
public void Walk() {
System.out.println("Girl is walking...");
}
}
public class HumanFactory {
public static Human createHuman(String m){
Human p = null;
if(m == "boy"){
p = new Boy();
}else if(m == "girl"){
p = new Girl();
}
return p;
}
}
4、Java标准库中的工厂设计模式
对于java.util.Calendar,通过传递不同的参数,getInstance()返回不同的日历实例。
java.util.Calendar – getInstance() java.util.Calendar – getInstance(TimeZone zone) java.util.Calendar – getInstance(Locale aLocale) java.util.Calendar – getInstance(TimeZone zone, Locale aLocale) java.text.NumberFormat – getInstance() java.text.NumberFormat – getInstance(Locale inLocale)
翻译自 Java Design Pattern: Abstract Factory
抽象工厂模式在工厂模式的基础上又增加了一层抽象。将抽象工厂模式与工厂模式比较,很明显是添加了一个新的抽象层。抽象工厂是一个创建其他工厂的超级工厂。我们可以把它叫做“工厂的工厂”。
抽象工厂类图
抽象工厂的Java代码
interface CPU {
void process();
}
interface CPUFactory {
CPU produceCPU();
}
class AMDFactory implements CPUFactory {
public CPU produceCPU() {
return new AMDCPU();
}
}
class IntelFactory implements CPUFactory {
public CPU produceCPU() {
return new IntelCPU();
}
}
class AMDCPU implements CPU {
public void process() {
System.out.println("AMD is processing...");
}
}
class IntelCPU implements CPU {
public void process() {
System.out.println("Intel is processing...");
}
}
class Computer {
CPU cpu;
public Computer(CPUFactory factory) {
cpu = factory.produceCPU();
cpu.process();
}
}
public class Client {
public static void main(String[] args) {
new Computer(createSpecificFactory());
}
public static CPUFactory createSpecificFactory() {
int sys = 0; // based on specific requirement
if (sys == 0)
return new AMDFactory();
else
return new IntelFactory();
}
}
实际使用的例子
事实上,现代的框架,抽象是一个非常重要的概念。 “Abstract factory pattern on top of IoC?”是stackoverflow上的一个关于抽象工厂的问题。
翻译自 Java Design Pattern: Builder
生成器模式的主要特征是,通过一步一步的方式生成一些东西。每个生成的东西,即使其中的任何一步都不相同,但也将遵循同样的过程。
在下面的故事中,我们定义一个饮料生成器StarbucksBuilder,用来生成星巴克饮料。StarbucksBuilder有几个步骤来建立一杯星巴克的饮料,如buildSize()和buildDrink()。最后返回生成的饮料。
1、Builder设计模式的类图
2、Builder设计模式的Java代码示例
package designpatterns.builder;
// produce to be built
class Starbucks {
private String size;
private String drink;
public void setSize(String size) {
this.size = size;
}
public void setDrink(String drink) {
this.drink = drink;
}
}
//abstract builder
abstract class StarbucksBuilder {
protected Starbucks starbucks;
public Starbucks getStarbucks() {
return starbucks;
}
public void createStarbucks() {
starbucks = new Starbucks();
System.out.println("a drink is created");
}
public abstract void buildSize();
public abstract void buildDrink();
}
// Concrete Builder to build tea
class TeaBuilder extends StarbucksBuilder {
public void buildSize() {
starbucks.setSize("large");
System.out.println("build large size");
}
public void buildDrink() {
starbucks.setDrink("tea");
System.out.println("build tea");
}
}
// Concrete builder to build coffee
class CoffeeBuilder extends StarbucksBuilder {
public void buildSize() {
starbucks.setSize("medium");
System.out.println("build medium size");
}
public void buildDrink() {
starbucks.setDrink("coffee");
System.out.println("build coffee");
}
}
//director to encapsulate the builder
class Waiter {
private StarbucksBuilder starbucksBuilder;
public void setStarbucksBuilder(StarbucksBuilder builder) {
starbucksBuilder = builder;
}
public Starbucks getstarbucksDrink() {
return starbucksBuilder.getStarbucks();
}
public void constructStarbucks() {
starbucksBuilder.createStarbucks();
starbucksBuilder.buildDrink();
starbucksBuilder.buildSize();
}
}
//customer
public class Customer {
public static void main(String[] args) {
Waiter waiter = new Waiter();
StarbucksBuilder coffeeBuilder = new CoffeeBuilder();
//Alternatively you can use tea builder to build a tea
//StarbucksBuilder teaBuilder = new TeaBuilder();
waiter.setStarbucksBuilder(coffeeBuilder);
waiter.constructStarbucks();
//get the drink built
Starbucks drink = waiter.getstarbucksDrink();
}
}
3、Builder的设计模式的实际使用
Builder模式已被用于很多类库。下面是Java核心编程里的一个例子。
StringBuilder strBuilder= new StringBuilder();
strBuilder.append("one");
strBuilder.append("two");
strBuilder.append("three");
String str= strBuilder.toString();
append()方法就像是我们的星巴克的例子中的一个步骤,toString()方法是最后一步。从这个语句看,我们可以很容易地理解 字符串是不可改变的 这个问题。
以上类图较为复杂,但和StringBuilder继承自AbstractStringBuilder一样,正是生成器模式所表现的意思。
4、生成器模式和工厂模式之间的差异
当需要多个步骤来创建一个对象的时候,使用生成器模式。当需要通过调用一个方法就很容易就创建了整个对象的时候,使用工厂模式。
翻译自 Java Design Pattern: Prototype
原型设计模式用在当需要经常使用非常相似的对象的情况下,当需要相似的对象时,原型模式会克隆原始对象并且只修改不同的地方,这样会消耗更少的资源。想想为什么有更少的资源消耗?
1、原型模式类图
2、原型模式的Java示例
package designpatterns.prototype;
//prototype
interface Prototype {
void setSize(int x);
void printSize();
}
// a concrete class
class A implements Prototype, Cloneable {
private int size;
public A(int x) {
this.size = x;
}
@Override
public void setSize(int x) {
this.size = x;
}
@Override
public void printSize() {
System.out.println("Size: " + size);
}
@Override
public A clone() throws CloneNotSupportedException {
return (A) super.clone();
}
}
//when we need a large number of similar objects
public class PrototypeTest {
public static void main(String args[]) throws CloneNotSupportedException {
A a = new A(1);
for (int i = 2; i < 10; i++) {
Prototype temp = a.clone();
temp.setSize(i);
temp.printSize();
}
}
}
3、Java标准库中的原型模式
java.lang.Object – clone()
由于博主水平有限,抱着锻炼为主的目的而翻译,若有不准确之处,请包涵,欢迎批评指正。