创建型
创建型模式提供了多种不同的方法从实例化它们的代码中除去了对这些具体类的显示引用。
1.1 抽象工厂(Abstract Factory)
结构图
代码实例
public class ScrollBar //Abstract Product
{
public ScrollBar()
{}
}
public class MotifScrollBar : ScrollBar //Concrete Product
{
public MotifScrollBar()
{}
}
public class PMScrollBar : ScrollBar //Concrete Product
{
public PMScrollBar()
{}
}
public class Window //Abstract Product
{
public Window()
{}
}
public class MotifWindow : Window //Concrete Product
{
public MotifWindow()
{}
}
public class PMWindow : Window //Concrete Product
{
public PMWindow()
{}
}
public abstract class WidgetFactory //Abstract Factory
{
public WidgetFactory()
{
Console.WriteLine("WidgetFactory .cotr");
}
public abstract ScrollBar CreateScrollBar();
public abstract Window CreateWindow();
}
public class MotifWidgetFactory : WidgetFactory //Concrete Factory
{
public MotifWidgetFactory ()
{
Console.WriteLine("MotifWidgetFactory .cotr");
}
public override ScrollBar CreateScrollBar()
{
Console.WriteLine("MotifWidgetFactory::CreateScrollBar");
return null;
}
public override Window CreateWindow()
{
return null;
}
}
public class PMWidgetFactory : WidgetFactory //Concrete Factory
{
public PMWidgetFactory () {}
public override ScrollBar CreateScrollBar()
{
Console.WriteLine("PMWidgetFactory::CreateScrollBar");
return null;
}
public override Window CreateWindow()
{
return null;
}
}
public class App
{
public static void Main (string[] args)
{
WidgetFactory w = new MotifWidgetFactory();
ScrollBar scroll = w.CreateScrollBar();
Console.ReadLine();
}
}
效果
优点:
1. 分离了具体的类 (产品类名被分离到了具体工厂中)
2. 它使得易于交换产品系列(因为具体工厂的创建只出现一次,所以可以直接替换)
3. 它有利于产品的一致性 (比较容易的实现一次应用只使用一个系列的产品,通常把一个具体工厂实现为Singleton)
缺点:
4. 难以支持的新种类(新种类的添加,涉及到抽象工厂的及其子类的改变)
1.2 生成器(Builder)
结构图:
代码实例:
public interface Builder
{
void buildPartA();
void buildPartB();
void buildPartC();
Product getResult();
}
public class Director
{
private Builder builder;
public Director( Builder builder )
{
this.builder = builder;
}
public void construct()
{
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}
Usage:
ConcreteBuilder builder = new ConcreteBuilder();
Director director = new Director( builder );
director.construct();
Product product = builder.getResult();
由Director来指导Builder怎么装配产品(因为产品的装配代码是封装在Director内部的),也就是说,这里可以替换Director来达到,用相同部件产生(转配)不同产品的效果
效果:
Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们.用户不知道内部的具体构建细节.Builder模式是非常类似抽象工厂模式,它将构建复杂对象的过程和它的部件解耦,就是为了将部件和组装过程分开。
1.3 Factory Method(工厂方法)
结构图:
代码实例:
public class Factory
{
public static Sample creator(int which)
{
if (which==1)
return new SampleA();
else if (which==2)
return new SampleB();
}
}
效果:
抽象工厂和工厂方法,这两个模式区别在于需要创建对象的复杂程度上。如果我们创建对象的方法变得复杂了,如上面工厂方法中是创建一个对象Sample,如果我们还有新的产品接口Sample2.
这里假设:Sample有两个concrete类SampleA和SamleB,而Sample2也有两个concrete类Sample 2A 和SampleB2
那么,我们就将上例中Factory变成抽象类,将共同部分封装在抽象类中,不同部分使用子类实现,这样就扩展出了抽象工厂 。
1.4 Prototype (原型)
结构图:
代码实例:
public abstract class PrototypeApple
{
protected string Odour;
public abstract string GetOdour();
public virtual object Clone()
{
return base.MemberwiseClone();
}
}
public class RedApple : PrototypeApple
{
public RedApple()
{
this.Odour = "good";
}
public override object Clone()
{
return base.Clone ();
}
public override string GetOdour()
{
return this.Odour;
}
}
public class GreenApple : PrototypeApple
{
public GreenApple()
{
this.Odour = "bad";
}
public override object Clone()
{
return base.Clone ();
}
public override string GetOdour()
{
return this.Odour;
}
}
public class ClientBoy
{
public void EatApple(PrototypeApple _apple)
{
PrototypeApple a = (PrototypeApple)_apple.Clone();
Console.WriteLine(a.GetOdour());
}
}
class Class1
{
[STAThread]
static void Main (string[] args)
{
ClientBoy b = new ClientBoy();
b.EatApple(new RedApple());
b.EatApple(new GreenApple());
Console.ReadLine();
}
}
效果:
原型模式隐藏了具体的产品类,因此减少了客户知道的名字数量,它是客户无需改变就可以使用新的产品。
优点:
运行时刻增加删除产品,用类动态配置应用
缺点:
每个产品必须实现Clone方法,这在一定场合比较困难,因为要决定是深还是浅拷贝对象不是件容易的事。
1.5 Singleton (单件)
结构图:
代码实例:
1.
public class Singleton
{
private static Singleton _instance = null;
protected Singleton()
{}
public static Singleton Instance()
{
lock(typeof(Singleton))
{
if(_instance==null)
_instance = new Singleton();
}
return _instance;
}
}
2.
public class Singleton
{
protected Singleton(){}
private static Singleton _instance = null;
static Singleton(){
_instance = new Singleton();
}
public static Singleton Instance()
{
return _instance;
}
}
效果:
Ps:
问题:
单件模式的类在运行时只有一个实例,也就是说其他对象都使用这个实例进行操作,那为什么不把这个类的所有方法都设计为静态的呢,那样岂不是更简单。
Sunmast 的回复:
.NET可以使用静态方法作为Singleton模式的实现,但是如果这么设计那么这个class就失去了面向对象的所有特性,有时候我们还是需要让这个class继承其他class,或者让其他class继承,等等类似问题
acewang 的回复:
收藏过阎宏博士在Java版的一段讲解,贴出来分享
------------------------------------------------------------
如果所有的方法都是静态的,那就根本不需要任何实例。有人把这种类叫做工具类,这种做法叫做工具类模式。
工具类模式基本上不需要面向对象的概念。
当然,我不是说面向对象的技术就一定比面向过程的好很多,但是如果你是在使用Java这样的面向对象的语言,设计一个面向对象的系统,那么一个单纯的想法就是尽量靠近面向对象的概念。我没有见过一个使用Java的人反其道而行之,努力使用面向过程的概念。如果你是面向过程概念的拥护者,不妨选择一个像Fortran这样的结构化编程语言。
在大多数的情况下,工具类中的方法都描述一些实体,应该把这些方法移动到描述这些实体的类中去。如果没有这些类,那就不妨考虑创建它们。
我曾经见到过一个很大的工具类,都是对String的操作。经过辨认,发现这些操作实际上都是为了组合URL准备的,并不是一般性地针对任何的String。为什么不把它们放到一个CustomizedURL类中去呢?
当你这样做了之后,会发现你并不需要一个很大的工具类,或者根本就可以取消它。
单例模式并不是一个取代工具类模式的好候选人。单例模式的情况在多JVM的J2EE服务器环境中变得很复杂。单例对象一旦创建出来就不会被湮灭,浪费内存。