Posted on 2007-03-17 17:01
dennis 阅读(962)
评论(1) 编辑 收藏 所属分类:
模式与架构 、
java 、
C#历程
系统的演化应当依赖于组合,而不是继承;这就提出了将类的实例化委托给一个对象的要求,因此创建型模式将变的越来越重要。
创建型模式属于对象创建模型。所谓对象创建模型就是说将实例化的工作委托给另一个对象来做。与之相对应的是类创建模型,这是一种通过继承改变被实例化的类。
创建型模式有两个重要的特点:
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#)》两书