Yhzhtk's Blog

(热爱技术,高效Code)     归档  标签  源码  关于 


创造型设计模式 - 单例、工厂、抽象工厂、生成器、原型

2013-11-04    设计模式  翻译  单例  工厂  抽象工厂  生成器  原型 


设计模式中的创造型模式,包括单例模式、工厂模式、抽象工厂模式、生成器模式、原型模式,本文主要用简单的实例介绍这几种设计模式。

·   单例模式 - 美国只有一个总统 原文 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


1、Java设计模式:单例模式

翻译自 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

2、Java设计模式:工厂模式

翻译自 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)

3、Java设计模式:抽象工厂

翻译自 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上的一个关于抽象工厂的问题。


4、Java设计模式:生成器模式

翻译自 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、生成器模式和工厂模式之间的差异

当需要多个步骤来创建一个对象的时候,使用生成器模式。当需要通过调用一个方法就很容易就创建了整个对象的时候,使用工厂模式。


5、Java设计模式:原型模式

翻译自 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()

由于博主水平有限,抱着锻炼为主的目的而翻译,若有不准确之处,请包涵,欢迎批评指正。





Load Disqus comments, wait a moment..

分类标签

jekyll3   编码1   windows1   bootstrap1   git3   删除1   命令3   python11   ide1   学习笔记3   实例分析1   mp3-tag1   github1   gravatar1   goagent1   翻墙1   C#4   找茬工具1   微博自动评论1   电脑监控1   备份1   云搜索1   wxPython1   py2exe1   yaml1   Eric1   PyQt1   Django1   设计模式5   翻译4   单例1   工厂1   抽象工厂1   生成器1   原型1   适配器1   桥接1   组合1   装饰1   外观1   享元1   代理1   MVC1   观察者1   状态1   策略1   模板1   访问者1   职责链1   解释器1   迭代器1   中介者1   备忘录1   js1   resize bar1   geohash1   口琴1   rpm安装gitlab1   CentOs1   WordPress1   数据库1   读脏数据1   丢失的修改1   不可重复读1   幻影读1   1   隔离1   思维导图1   事务1   笔记迁移1   note1   issue1  

最新博文

最新评论

Feed订阅


©2013 首页   关于     View me on GitHub Powered by Jekyll & Bootstrap 知识共享许可协议