Pattern (1)

Chapter 1 Introduce of Patterns
Factory pattern :根据提供给工厂的数据,从一系列相关的类中选择一个类实例并返回。
Abstract Factory:用于返回一组类中的一个,在某些情况下,它实际上为一组类返回了一个工厂。
Bulider Pattern :根据提供给它的数据及其表示,将一系列对象组装成一个新对象。通常选择何种方式组装对象由工厂决定。
当创建新实例代价较高的时候,原型模式拷贝或克隆一个现有的类,而不是创建一个新实例。
单件模式可以保证有切只有一个对象实例,并提供一个该实例的全局访问点。
Adapter Pattern :用于讲一个类的接口转换成另一个类的接口。
桥接模式:可以将一个类的接口和它的实现分离,这样可以不用修改客户端代码就能改变或替换实现过程。
组合模式:是一个对象的集合,其中的任何一个对象既可以是一个组合,也可以时一个叶子对象。
装饰模式:用一个类包装给定的类,并为它添加新的功能,将所有未改动的方法传递给下面的类。
外观模式:将一系列复杂的对象放在一起,并提供一个新的、更简单的访问这些数据的接口。
享元模式:把一部分的类数据移到类外部。在执行方法是将数据传递进来,通过这种方式限制那些又小又相似的实力的增加数量。
代理模式:为一个比较复杂的对象提供一个简单的占位对象,实例画该复杂对象在某种程度上比较浪费时间或代价较高。
行为型模式(Behavioral Pattern)通常和对象之间的通信有关。包括几种模式:
职责链(Chain of Responsibility)把请求从链中的一个对象传递到下一个对象,直到请求被响应为止。通过这种方式在对象之间去除耦合。
命令模式(Command Pattern)用简单的对象表示软件命令的执行,支持等如和取消操作。
 
解释器模式(Iterpreter Pattern)提供一个如何把语言元素包含在程序中的定义。
迭代器模式(Iterator pattern)提供了一种顺序访问一个类中的一系列数据的方式。
中介者模式(Mediator Pattern)定义了如何用一个对象简化对象之间的通信,使对象之间不必相互了解。
备忘录模式(Memento Pattern)定义了如何保存一个类实例的内容一边以后能恢复它。
观察者模式(Observer Pattern)定义了一种把改动通知给多个对象的方式。
状态模式(State Pattern)允许一个对象在其内部状态改变时修改它的行为。
策略模式(Strategy Pattern)将算法封装到类里。
莫板方法模式(Template Method Pattern)提供了算法的一个抽象定义。
访问者模式(Visitor Pattern)在不改变类的前提下,为一个类添加多种操作。
 
 
Chapter 2 Factory Pattern
 
Simple Factory Pattern
Question:什么时候可以使用类工厂?使用类工厂有无类似的结构框架?使用该工厂还有什么其它问题吗?
在需要向系统添加一些新类型的时候,最明智的做法就是先利用多态为这些新类型创建一个公共接口,而后就可以通过多态调用新的类。然而这仍然存在一个问题,如果用与创建对象的那部分代码分散在整个程序里(如再某种条件下创建A,当条件更改时创建B),你仍然需要找出所有与类型相关的代码。类工厂就为将创建一个类的代码集中到一块提供了实现。这使得系统的其余部分的代码与新加入的那些特定类型相分离。最为直接的例子就是向工厂方法传入具体的Type信息返回指定的实例:
public class ClassFactory
{
 public object GetClass(Type ){ //返回Type对应的类型实例}
}
如果我们不使用类工厂,创建对象时,我们可能面对if-else语句:
if( type = type_A){ ClassA obj = new ClassA();}else{ ….}
 
Polymorphic Factories
在《设计模式》中强调Factory Method是为了使不同类型的工厂可以由基本类型的工厂派生出来。
public interface IMyInterface{ void DoSomething();}
public abstract class MyFactory
{
 protected abstract IMyInterface Create();
 static Hashtable factories = new Hashtable();
public static void AddFactory
(string id, MyFactory f){factories. Add(id ,f);}
public static IMyInterface CreateClass(string id)
{
   return (MyFactory)factories.Key[id].Create();
}
}
public class A : IMyInterface
{ public void DoSomething(){}}
class FactoryA :MyFactory
{
protected IMyInterface Create(){return new A();}
public FactoryA()
{
 if(! MyFactory.factories.ContainsKey[“FactoryA”])
{ MyFactory.AddFactory(“FactoryA”,new FactoryA());}
}
}
将新类完全中同其它的代码分离开,这便是多态工厂的基本思想。当你想向系统添加新类,首先要做的就是派生出一个子类工厂,该子类工厂的create方法返回实现了IMyInterface的对象。而后将该新类工厂添加到factories表中。
 
Factory Method Pattern
该模式不是用一个专门的类来决定实例化哪一个子类。相反,超类把这种决定延迟到每个子类。这种模式实际上没有决策略点,即没有直接选择一个子类实例化的决策。按这种模式编写的程序定义了一个抽象类,它去定义Factory Method,但这工厂方法由其子类覆盖。
public abstract class Factory { public abstract ReturnType GetClass(); }
public abstract class FactoryA
{ public override ReturnType GetClass(){ return new ReturnType_A();}}
对这中模式我持有怀疑的态度,这也能算时工厂模式吗?对于两个超类,其派生类之间的关系若是一对多,则可以用上面的代码来表示。
 
Abstract Factory Pattern
当要返回一些列相关类中的某一个,而每个类都能根据需要返回不同的对象时,可以使用这种模式。在某些情况下,它实际上为一组类返回了一个工厂。
基本思想:在创建工厂对象的地方,由你来决定如何使用该工厂对象创建那些对象。例:
    // 创建一个通用的游戏环境,而且还向要支持不同类型的游戏
    public interface IObstacle { void Action();}
public interface IPlayer { void InteractWith(IObstacle o);}
    public class Kitty :IPlayer { public void InteractWith(IObstacle o){ o.Action(); }}
    public class Puzzle :IObstacle{ public void Action(){Console.WriteLine("Puzzle");}}
 
    //the abstract Factory
    public interface IGameElementFactory
    {
        IPlayer MakePlayer();
        IObstacle MakeObstacle();
    }
    //concrete factories
    public class KittiesAndPuzzles:IGameElementFactory
    {
        public IPlayer MakePlayer() {    return new Kitty();   }
        public IObstacle MakeObstacle()    {     return new Puzzle();      }  
 }
    public class GameEnvironment
    {
        IGameElementFactory gef;
        IPlayer p;
        IObstacle ob;
        public GameEnvironment(IGameElementFactory factory)
        {
            gef = factory;
            p = factory.MakePlayer();
            ob = factory.MakeObstacle();
        }
        public void Play() { p.InteractWith(ob); }
    }
}
抽象工厂IGameFactory将工厂对象的创建交给了实现该接口的具体类,如KittiesAndPuzzles类。而GameEnvironment则封装了工厂对象的调用。
抽象工厂和一般的接口实现又有什么区别呢?什么情况下可以使用抽象工厂呢?首先你的注意到IPlayer、和IObserver接口存在的意义。实现这两个接口的类才是实际上用到的类,它们之间的关系才是所有代码的重点。例中Kitty、Puzzle类就是你开发的游戏环境中Play()操作的执行者和实现者。它们是一个系统的组成部分、是整体的工件,为此抽象出IGameFactory接口。该接口将Kitty、Puzzle这样的相关类对象的创建集中到一起。而实现该接口的类便是具体的关系组合,你可以通过向这些类传入相关参数构造Kitty、Puzzle对象,即Concrete Factory。
抽象工厂模式也可以用抽象类来实现:
public abstract class GameFactory
{
IPlayer p;
        IObstacle ob;
public abstract IPlayer MakePlayer();
public abstract IObserver MakeObserver();
public GameFactory(){ p= MakePlayer(); ob = MakeObserver();}
public void Play(){p.InteractWith( ob); }
}
你可以通过派生出具体的PersonAndGame类具体化该抽象类:
public class PersonAndGame :GameFactory
{
 public IPlay MakePlayer(){ return new Kitty();}
 public IObserver MakeObserver(){return new Puzzly(); }
 }
这里GameFactory也可以称为抽象工厂。
抽象工厂的一个主要目的是它能隔离要生成的具体类。这些类的实际类名隐藏在工厂里,在客户端根本不需要知道,如上面的kitty、Puzzly类。
 
 
Chapter 3 Singleton Pattern
Singleton 提供一种方法使得某一特定类型存在一个,并且只能是一个对象。它实际上可以认为是对象池的一个特例。它可以提供一个全局的存取点,以及注册、查找功能。注册和查找是相关联的。Singleton Pattern的关键是防止用户以其它任何方式创建对象,而只能用你所提供的方式。所有的构造函数必须被声明为私有的,而且必须至少声明一个构造函数。
public static class Singleton
{
 static Singleton()
{//静态类只能由私有的静态构造函数,因为静态类不能被实例化}
 public static ArrayList arrayList;
 public static void Registry( IMyClass obj){ arrayList.Add(obj)}
 public static bool LookUp(IMyClass obj){ … }
}
我测试了类的静态构造函数,它不但允许你实例化对象,同时更让你能够在调用静态方法做些初始化工作。但由于静态方法必须是无参数的,因此你也就不能重载静态构造函数,也就是说,静态构造函数只能存在一个。
单件模式样例:
    public class Singleton
    {
        static bool isRun = false;
        Singleton() {}
        public static Singleton getSingleton()
        { if (!isRun) { return new Singleton(); } else { return null; } }
}
单件模式应用程序:
public static class SingletonApp
    {
        static Mutex m_Mutex;
        public static void Run(Form mainForm)
        {
            bool first = IsFirstInstance();
            if (first)
            { Application.ApplicationExit += OnExit; Application.Run(mainForm);}
        }
        static bool IsFirstInstance()
        {
            Assembly assembly = Assembly.GetEntryAssembly();
            string name = assembly.FullName;
            m_Mutex = new Mutex(false, name);
            bool owned = false;
            owned = m_Mutex.WaitOne(TimeSpan.Zero, false);
            return owned;
        }
        static void OnExit(object sender, EventArgs args)
        { m_Mutex.ReleaseMutex();   m_Mutex.Close(); }
        //Other overloaded versions of Run( )
    }
当然你也可以向上面代码添加修饰,如异常管理等。
Singleton模式并没有限制只能创建一个对象,也允许你创建固定数量的对象。对于固定数量的对象,你必须处理对象池的对象如何共享这种问题。
对象池管理机制下的单件模式样例:
    public class PoolManager
    {
        static class PoolItem
        {
           public bool inUse = false;   public object item;
           public PoolItem(object item) { this.item = item; }
        }
        ArrayList items = new ArrayList();
        public PoolManager(object item) { items.Add(new PoolItem(item)); }
        public object Get()
        {
            for (int i = 0; i < items.Count; i++)
            { PoolItem pitem = (PoolItem)items[i];
               if (pitem.inUse == false) { pitem.inUse = true; return pitem.item; }
}
return null;
        }
        public void Release(object item)
        {
            for (int i = 0; i < items.Count; i++)
            {   PoolItem pitem = (PoolItem)items[i];
                if (item == pitem.item) { pitem.inUse = false; return; }
            }
        }
 }
在该对象池管理下的单件模式:
    public class PoolSingleton
    {
        static PoolManager pool = new PoolManager();
        public static void AddObject(int number)
       {
            for (int i = 0; i < number; i++) { pool.Add(new PoolSingleton()); }
        }
        public static PoolSingleton GetObject() { return (PoolSingleton )pool.Get(); }
        public static void ReleaseObject(PoolSingleton o) { pool.Release(o); }
 }
这里你只能通过静态方法AddObject创建新的对象,只能通过GetObject方法从对象池中取得单件对象的一个引用。
 
Chapter 4 Builder Pattern
Builder模式:你可以用同样的步骤创建不同的对象体。该模式主要是为了将对象的构造与它的“表示”分离开来,这样对象就可以有多个不同的”表示”。它同Abstract Factory模式的主要区别在于该模式遵循一定的步骤一步步创建对象。
该模式具有以下几个效果:
1、                生成器允许读者改变产品的内部表示,同时也隐藏了产生如何组装的细节;
2、                每个特定的生成器都独立于其它的生成器,同时独立于程序的其它部分,这一点提高了对象的模块性,并使添加其它的生成器变得相对简单。
3、                由于每个生成器是根据数据一步一步构建最终结果,所以能精确地控制生成器的每个结果。
生成器样例:
    public abstract class MyClass{ public abstract void DoSomething(); }
    public abstract class Builder { public abstract void Build(); }// 开始构建
    public class A :MyClass{}
public class BuilderA
{A a; public override void Build(){// 更具a对象组合处Builder对象 }}
    // 下面类是:操作、显示MyClass的派生类的控制类。
    public class Director
    {
        Builder b;
        public Director(Builder b){ this.b = b; }
        public returnType ShowOrOperate(){ b.Build(); return returnType_object; }
}
你只要向Director类构造函数传入Builder类或其派生类对象就可以显示或说表示其欲表示的行为特征。Builder类也可以理解为MyClass类的表示类,一般的MyClass类的子类对象有其相对应的Builder类的子类来表示其行为特征。
都说Abstract Factory模式同该模式很相似,而这相似表现在那呢?下面看一个类似定义的Abstract Factory模式程序:
    public abstract class MyClass{ public abstract void DoSomething(); }
    public abstract class Factory { public abstract MyClass GetObject();}
    public class A :MyClass{}
    public class FactoryA { public override MyClass GetObject() { return new A(); } }
    public class WorkEnvironment
    {
        Factory f; MyClass a;
        public WorkEnvironment(Factory f) { f = this.f; a = f.GetObject(); }
        // 对a对象的其他操作
 }
从这段代码从看,我觉得二者的区别在于最终返回的对象不同,生成器模式要求操作、显示的对象是Builder类的派生类;而抽象工厂模式则是为了获得MyClass派生类对象进而对其进行操作,而其FactoryA类在这仅仅是作为一种媒介。
 
Chapter 5 Prototype Pattern
该模式通过某个原型的实例来创建对象。当程序中确定了所需要的同要类,但需要将具体类延迟到运行时才能确定时,可以使用这种模式。它同Builder模式一样都由某些类确定组成最终类的部件或细节。然而ProtoType模式中目标类的构建是通过克隆一个或多个原型类,然后按预期的行为更改或补充被克隆类的细节而实现的。
    // 对一个数组的克隆
    public class MyData : ICloneable
    {
        public MyData(ArrayList a) { array = a; }
        protected ArrayList array;
        public object Clone()
        {
            ArrayList a = new ArrayList();
            for (int i = 0; i < array.Count; i++)   { a[i] = array[i]; }
            MyData newData = new MyData(a);    return newData;
        }
    }
这里我们返回的是object对象,使用前必须转换为MyData类型对象。克隆该类型对象同数组对象的复制不同之处在于复制的是数组对象的引用指针,而这里则是拷贝数组元素。 如:
ArrayList a = array;
则两个数组具有相同的引用,无论对a或array对象的任何操作同样影响另外一个对象。
    而这里克隆的仅仅是底层数据的不同,数据a同array是两个不同的对象,具有不同的引用指针。只有当你修改了数组对象所引用的底层数据才会影响到另外一个数组。 而对数组本身的Sort这类的方法则是互补影响的。
    在需要创建大量的类时,或者在创建类后又要修改时,都可以使用原型模式。只要所有的类都具有相同的接口,它们就都能完成不同的操作。
Prototype模式的另一个较好的例子就是当你想对一个表对象实现类似:Select Col, col2, col3 from table order by ?
的功能。按col1或col2、col3显示的结果都不相同。
当具体类的个数较多时,如对一个表按不同排序显示,你可以考虑使用原型管理器,下面就是一个原型管理器样例:
    public class Table { public Table Clone() { return new Table(); } }
    public class SortByA { Table table; // 克隆对象}
    public class SortByB { Table table; // 克隆对象}
    public class Prototype
    {
        SortByA a ;    SortByB b;
        public void ShowData(SortByA a) { this.a = a; // 显示按A排序的结果 }
        public void ShowData(SortByB b) { this.b = b;  // 显示按B排序的结果 }
}
你将原型注册到原型管理其中,而后重载ShowData方法实现具体类操作。
克隆:可以通过克隆一个类,而对数据对象操作。也可以做深层克隆,即克隆类的结构、数据等,而不仅仅是克隆类对象的结构、和指向数据的指针。
在什么时候克隆更好呢?如果每次派生一个特别相似的新类时,都要重新Clone方法,这不太令人满意。更好的方案是取消让每个类都取实现Clone方法的IConeable接口,把这个处理过程改为让每个接受类克隆发送类中的数据。
  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值