系统的演化应当依赖于组合,而不是继承;这就提出了将类的实例化委托给一个对象的要求,因此创建型模式将变的越来越重要。
创建型模式属于对象创建模型。所谓对象创建模型就是说将实例化的工作委托给另一个对象来做。与之相对应的是类创建模型,这是一种通过继承改变被实例化的类。
创建型模式有两个重要的特点:
1) 客户不知道创建的具体类是什么(除非看源代码)
2) 隐藏了类的实例是如何被创建和放在一起的
一。抽象工厂模式
1.意图:提供一个创建
一系列相关或相互依赖对象的接口,而无需指定它们的具体的类。
2.适用场景:
1)一个系统要独立于它的产品的创建、组合和表示时
2)一个系统要由多个产品系列中的一个来配置时
3)当你要强调一系列相关的产品对象的设计以便进行联合使用时
4)当你提供一个产品类库,而只想显示它们的接口而不是实现时
3.UML图——结构
4.效果:
1)分离了具体的类,通过抽象接口将客户与具体的类分离
2)易于交换产品系列
3)有利于产品的一致性
4)难以支持新种类的产品,比如我们现在有一个ProductC产品,我们需要增加类AbstractProductC,增加AbstractFactory:: CreanteProductC方法,并且两个产品系列的实际创建者ConCreateFactory1、ConCreateFactor2都要实现该方 法。
可以通过给方法加参数的方式来指明创建的是什么产品,这样客户代码就无需改变,只要传递不同的参数。AbstractFactory类只需要提供一个CreateProduct(const string& name)方法即可。
5.代码实现,以《深入浅出设计模式(java C#)》的动物工厂为例:
using
System;
namespace
AnimalWorld {
//
抽象大陆工厂
abstract
class
ContinentFactory {
abstract
public
Herbivore CreateHerbivore();
abstract
public
Carnivore CreateCarnivore(); }
//
非洲大陆,有角马,狮子
class
AfricaFactory : ContinentFactory {
override
public
Herbivore CreateHerbivore() {
return
new
Wildebeest(); }
override
public
Carnivore CreateCarnivore() {
return
new
Lion(); } }
//
美洲大陆,有狼,野牛
class
AmericaFactory : ContinentFactory {
override
public
Herbivore CreateHerbivore() {
return
new
Bison(); }
override
public
Carnivore CreateCarnivore() {
return
new
Wolf(); } }
//
食草动物"
abstract
class
Herbivore { }
//
肉食动物"
abstract
class
Carnivore {
//
猎食食草动物的方法
abstract
public
void
Eat( Herbivore h ); }
//
角马
class
Wildebeest : Herbivore { }
//
狮子"
class
Lion : Carnivore {
//
重载猎食食草动物的方法
override
public
void
Eat( Herbivore h ) { Console.WriteLine(
this
+
"
eats
"
+
h ); } }
//
野牛
class
Bison : Herbivore { }
//
狼
class
Wolf : Carnivore {
//
重载猎食食草动物的方法
override
public
void
Eat( Herbivore h ) { Console.WriteLine(
this
+
"
eats
"
+
h ); } }
//
动物世界类
class
AnimalWorld {
private
Herbivore herbivore;
private
Carnivore carnivore;
//
创建两种动物分类
public
AnimalWorld( ContinentFactory factory ) { carnivore
=
factory.CreateCarnivore(); herbivore
=
factory.CreateHerbivore(); }
//
运行食物链
public
void
RunFoodChain() {
//
肉食动物猎食食草动物
carnivore.Eat( herbivore ); } }
///
<summary>
///
抽象工厂模式客户应用测试
///
</summary>
class
GameApp { [STAThread]
static
void
Main(
string
[] args) {
//
创造并运行非洲动物世界
ContinentFactory africa
=
new
AfricaFactory(); AnimalWorld world
=
new
AnimalWorld( africa ); world.RunFoodChain();
//
创造并运行美洲动物世界
ContinentFactory america
=
new
AmericaFactory(); world
=
new
AnimalWorld( america ); world.RunFoodChain(); Console.Read(); } } }
二。Builder模式
1.意图:将一个
复杂对象的构建与它的表示相分离,使得同样的构建过程可以创建不同的表示(或者说产品)
2.适用场景:
1)当创建复杂对象的算法应该独立于改对象的组成部分以及它们的装配方式时
2)当构造过程必须允许被构造的对象有不同的表示时
3.UML图——结构
Director接受一个Builder子类对象,完成创建过程,并通知Builder对象返回以及构造好的产品。
4.效果:
1)可以使你改变一个对象的内部表示
2)构造代码和表示代码分开
3)可以对构造过程进行更精细的控制
5。实现:以一个车辆建造过程为例(C#)
using
System;
namespace
CarShop {
using
System;
using
System.Collections;
//
指挥者,Director
class
Shop{
public
void
Construct( VehicleBuilder vehicleBuilder ){ vehicleBuilder.BuildFrame(); vehicleBuilder.BuildEngine(); vehicleBuilder.BuildWheels(); vehicleBuilder.BuildDoors(); } }
/*
"Builder 建造者",Builder 抽象建造者具有四种方法 装配框架 装配发动机 装配轮子 装配车门
*/
abstract
class
VehicleBuilder {
protected
Vehicle vehicle;
//
返回建造完成的车辆
public
Vehicle Vehicle{
get
{
return
vehicle; } }
abstract
public
void
BuildFrame();
abstract
public
void
BuildEngine();
abstract
public
void
BuildWheels();
abstract
public
void
BuildDoors(); }
//
具体建造者-摩托车车间
class
MotorCycleBuilder : VehicleBuilder {
override
public
void
BuildFrame(){ vehicle
=
new
Vehicle(
"
摩托车
"
); vehicle[
"
frame
"
]
=
"
MotorCycle Frame
"
; }
override
public
void
BuildEngine(){ vehicle[
"
engine
"
]
=
"
500 cc
"
; }
override
public
void
BuildWheels(){ vehicle[
"
wheels
"
]
=
"
2
"
; }
override
public
void
BuildDoors(){ vehicle[
"
doors
"
]
=
"
0
"
; } }
//
具体建造者-轿车车间
class
CarBuilder : VehicleBuilder {
override
public
void
BuildFrame(){ vehicle
=
new
Vehicle(
"
轿车
"
); vehicle[
"
frame
"
]
=
"
Car Frame
"
; }
override
public
void
BuildEngine(){ vehicle[
"
engine
"
]
=
"
2500 cc
"
; }
override
public
void
BuildWheels(){ vehicle[
"
wheels
"
]
=
"
4
"
; }
override
public
void
BuildDoors(){ vehicle[
"
doors
"
]
=
"
4
"
; } }
//
具体建造者-单脚滑行车车间
class
ScooterBuilder : VehicleBuilder {
override
public
void
BuildFrame(){ vehicle
=
new
Vehicle(
"
单脚滑行车
"
); vehicle[
"
frame
"
]
=
"
Scooter Frame
"
; }
override
public
void
BuildEngine(){ vehicle[
"
engine
"
]
=
"
none
"
; }
override
public
void
BuildWheels(){ vehicle[
"
wheels
"
]
=
"
2
"
; }
override
public
void
BuildDoors(){ vehicle[
"
doors
"
]
=
"
0
"
; } }
//
车辆产品类
class
Vehicle {
private
string
type;
private
Hashtable parts
=
new
Hashtable();
//
筑构函数,决定类型
public
Vehicle(
string
type ){
this
.type
=
type; }
//
索引
public
object
this
[
string
key ]{
get
{
return
parts[ key ]; }
set
{ parts[ key ]
=
value; } }
//
显示方法
public
void
Show() { Console.WriteLine(
"
\n---------------------------
"
); Console.WriteLine(
"
车辆类类型:
"
+
type ); Console.WriteLine(
"
框架 :
"
+
parts[
"
frame
"
] ); Console.WriteLine(
"
发动机 :
"
+
parts[
"
engine
"
] ); Console.WriteLine(
"
#轮子数:
"
+
parts[
"
wheels
"
] ); Console.WriteLine(
"
#车门数 :
"
+
parts[
"
doors
"
] ); } }
///
<summary>
///
建造者模式应用测试
///
</summary>
class
CarShop { [STAThread]
static
void
Main(
string
[] args) {
//
创造车间及车辆建造者
Shop shop
=
new
Shop(); VehicleBuilder b1
=
new
ScooterBuilder(); VehicleBuilder b2
=
new
CarBuilder(); VehicleBuilder b3
=
new
MotorCycleBuilder();
//
筑构并显示车辆
shop.Construct( b1 ); b1.Vehicle.Show(); shop.Construct( b2 ); b2.Vehicle.Show(); shop.Construct( b3 ); b3.Vehicle.Show(); Console.Read(); } } }
三。Factory Method模式
1.意图:定义一个用于创建对象的接口,让子类决定实例化具体的哪一个类。
2.适用场景:
1)当一个类不知道它所必须创建的对象的类的时候,让子类来决定
2)当一个类希望由它的子类来决定它所创建的对象的时候
3。UML图——结构:
4.效果:
1)为子类提供回调函数
2)连接平行的类层次
3) 创建函数可以接收参数来决定创建什么产品
4)Factory Method容易导致创建过多的Creator的子类以对应不同的产品,这个方法可以通过模板技术来解决
6.实现,手机工厂,产品可能是Nokia,也可能是Motorola
using
System;
using
System.Collections.Generic;
using
System.Text;
namespace
HandPhone {
//
手机接口
interface
Mobile {
void
call(); }
//
手机工厂接口
interface
MobileFactory { Mobile createMobile(); }
//
Nokia
class
Nokia:Mobile {
public
void
call() { Console.WriteLine(
"
This is a {0} phone
"
,
this
.GetType().Name); } }
//
Motorola
class
Motorola : Mobile {
public
void
call() { Console.WriteLine(
"
This is a {0} phone
"
,
this
.GetType().Name); } }
//
Motorola工厂
class
MotorolaFactory : MobileFactory {
public
Mobile createMobile() {
return
new
Motorola(); } }
//
Nokia工厂
class
NokiaFactroy : MobileFactory {
public
Mobile createMobile() {
return
new
Nokia(); } }
public
class
Client {
static
void
Main(String []args) { MobileFactory factory
=
null
; Mobile mobile
=
null
; factory
=
new
NokiaFactroy(); mobile
=
factory.createMobile(); mobile.call(); factory
=
new
MotorolaFactory(); mobile
=
factory.createMobile(); mobile.call(); } } }
四。Prototype模式
1.意图:通过原型实例指定创建对象的种类,并通过拷贝这些原型来创建新的对象
2.适用场景:
1)要实例化的类是在运行时刻指定的,比如动态装载
2)为了避免创建一个与产品层次平行的工厂类层次
3)当一个类的实例只能有几个不同的状态组合中的一种时,建立相应数目的原型并克隆它们可能比每次用合适的状态手工化该类更方便一些。
3.UML图——结构:
4.效果:
1)运行时动态增加或者删除产品
2)减少子类的构造数目
3)用类动态配置应用
4)动态指定新的对象,通过改变结构或者值
5)缺陷在于每一个Prototype的子类都需要实现clone操作
5。实现,无论java还是C#都从语言层次内置了对prototype模式的支持。具体不再详述。
五。singleton模式
1。意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点
2.适用场景:
1)当需要类只有一个实例,并且客户只能通过一个全局点去访问它
2)当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用扩展的实例
3.UML图:略
4.效果:
1)对唯一实例的受控访问
2)缩小命名空间
3)允许对操作和表示的细化
4)允许可变数目的实例
5实现,关于singleton在java多线程环境下的实现,请见讨论《
当Singleton遇到multi-threading》,C#对singleton多线程环境下的能够正确实现Double-checked模式:
public
sealed
class
Singleton {
private
static
volatile
Singleton instance;
private
static
object
syncRoot
=
new
Object();
private
Singleton() {}
public
static
Singleton Instance {
get
{
if
(instance
==
null
) {
lock
(syncRoot) {
if
(instance
==
null
) instance
=
new
Singleton(); } }
return
instance; } } }
本文仅作速查记忆用,摘记于《设计模式——可复用面向对象软件基础》和《深入浅出设计模式(java C#)》两书
文章转自庄周梦蝶 ,原文发布时间5.17
相关资源:敏捷开发V1.0.pptx