为什么不喜欢用attribute而用外部的metadata
修改不需要编译,用户现场只用记事本或者查询分析器就完成用户的需求对客户来说有吸引力。
可以做编辑器,让BA来控制流程和逻辑
借助用sql或者xsl,可以方便的修改和转换。
posted on 2005-09-24 23:24:00 by microhelper 评论(11) 阅读(4927)
随笔 - 74, 评论 - 431, 引用 - 7 |
||
为什么不喜欢用attribute而用外部的metadata修改不需要编译,用户现场只用记事本或者查询分析器就完成用户的需求对客户来说有吸引力。 可以做编辑器,让BA来控制流程和逻辑 借助用sql或者xsl,可以方便的修改和转换。 posted on 2005-09-24 23:24:00 by microhelper 评论(11) 阅读(4927) Internet Explorer Developer Toolbar Beta试用了一会儿,确实为开发带来一些便利。 官方介绍: OverviewThe IE Developer Toolbar provides several features for deeply exploring and understanding Web pages.
-- Explore and modify the document object model (DOM) of a web page. -- Locate and select specific elements on a web page through a variety of techniques. -- Selectively disable Internet Explorer settings. -- View HTML object class names, ID's, and details such as link paths, tab index values, and access keys. -- Outline tables, table cells, images, or selected tags. -- Validate HTML, CSS, WAI, and RSS web feed links. -- Display image dimensions, file sizes, path information, and alternate (ALT) text. -- Immediately resize the browser window to 800x600 or a custom size. -- Selectively clear the browser cache and saved cookies. Choose from all objects or those associated with a given domain. -- Choose direct links to W3C specification references, the Internet Explorer team weblog (blog), and other resources. -- Display a fully featured design ruler to help accurately align objects on your pages. The Developer Toolbar can be pinned to the Internet Explorer browser window or floated separately. 上一个随笔中Singleton第二个练习题的答案为1,2,那么为什么是不是创建了一个实例呢?
posted on 2005-09-19 10:57:00 by microhelper 评论(1) 阅读(3860) Design.Patterns.Step.By.Step.3单例模式 使用对象时最基本的事情就是要首先创建对象的实例,一般情况下,这是一件极其简单的事情,就是用new运算符来创建某个对象的实例,简单的人们都不想提及。然而有时候你会发现创建对象的实例也不是那么简单。 比如有一些类,在整个程序运行期间只允许一个实例,或者我们说如果有多个实例存在程序逻辑会变得难以控制,很可能遭遇错误,比如对程序所需要的资源如连接池之类的做集中管理。 或者从逻辑上讲,在整个程序运行期间可以只有一个实例,当然也可以创建多个实例,这对程序逻辑没有影响,但是实施强制单一对象实例的代价要远低于带来的收益。 全部强制对象单一机制有些多余,我们要比较实施强制措施的代价,而不同的实施方案代价和收益是不同的。 最原始方案的就是全局变量,程序开始运行时初始化这个全局变量,代码中每一个使用该类的地方都引用这个全局变量。 全局变量一个缺点是有些对象实例实际上很可能根本不会用到,而初始化又恰恰要花点时间。没有办法做到延迟加载,当然有聪明的人会说一样可以实现延迟加载,设置一个函数,每次通过这个函数来获得这个全局变量的引用,在函数里面会判断该全局变量的状态,如果没有初始化才作初始化的动作。实际上根本的缺点在于当这样的情况变得越来越多的时候,逻辑变得很复杂,代码变得难以控制,职责变得很不明确。 那么我们开始重构,将类的单一实例以及类初始化的职责封装起来,然后提供一个全局的访问点让其他的代码能够访问到这个单一的类的实例。简单的实现方式可能如下: public sealed class Singleton { static Singleton instance = null; private Singleton () {} public static Singleton Instance() { if (instance==null) {instance = new Singleton (); } return instance; } } 这里把Singleton类的构造函数设置为private是为了其他类不能直接用new方法来创建多个Singleton的实例并使用它,而是提供了一个全局的访问接口Instance()方法,其他的代码只能通过访问Instance方法来获得一个Singleton类的实例。在Instance()中会判断instance是否已经创建,如果没有创建的话才去创建一个实例出来。 练习题:为什么instance要声明为static类型的变量。 简单测试之后发现可以Singleton类这样的设计实现了我们的意图,那么我们再检查Singleton的代码 如果多个线程同时调用Instance()方法,而这时instance还没有被创建,这时会怎么样呢,怎样保持线程同步? 我们可以对Singleton做一点改造,用lock来强制线程同步 public sealed class SingletonLock { static SingletonLock instance=null; static readonly object padlock = new object(); private SingletonLock() {} public static SingletonLock Instance() { lock (padlock) { if (instance==null) {instance = new SingletonLock();} return instance; } } } 每次强制线程同步是很耗费资源的,而实际上只有第一次访问Instance()才需要强制线程同步以确保只创建一个实例,那么可以在锁定线程之前先判断instance是否为null,如果为null才调用lock锁定线程。 public static SingletonLock Instance() { if(instance==null) { lock (padlock) { if (instance==null) { instance = new SingletonLock(); } } } return instance; } java和c#为Singleton模式提供了天然的支持,于是我们有了更简单的实现方法。 public class Singleton { private static Singleton instance = new Singleton(); private Singleton(){} public static Singleton Instance() { return instance; } } static Singleton instance的static关键字确保instance在被载入AppDomain时被初始化,而且不会有多线程的困扰。这样在访问Instance()方法时,instance必定是已经创建好的,这样的代价就是失去了延迟加载的特性。 应该是the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class. 应用Singleton模式会有哪些代价呢,首先实现Singleton模式类的Singleton特性不能被子类天然继承,因为私有变量instance和公共方法Instance()都是静态的,而且基类的构造函数是private的。另外一点就是不透明,调用者知道自己在使用一个Singleton类,需要通过Instance()方法来获得实例。 在《敏捷软件开发 原则、模式与实践》中介绍了Monostate模式,Monostate模式使用静态变量来实现多个实例共享数据,这样多个类的实例使用起来像一个实例一样,Monostate的代价一方面在于多次创建对象并且销毁会有性能方面的损失,一方面将一个类改造成遵循Monostate模式的类比较麻烦。 Singleton强制结构单一,防止创造出多个对象实例,Monostate强制行为单一,所有的实例表现得像一个对象。 练习题: 1: 以前论坛经常有人争论全是静态函数的Library和遵循Singleton模式的Library孰优孰劣,静态函数的Library有什么缺点? 2: CreateSingleton()中instance.GetResource()的返回值分别是什么 public sealed class Singleton { static Singleton instance = null; private int sequence = 0; private Singleton() { } public static Singleton Instance() { if (instance==null) { instance = Initialize(); } return instance; } public int GetResource() { CreateSequence(); return sequence; } private static Singleton Initialize() { System.Threading.Thread.Sleep(200); return new Singleton(); } private void CreateSequence() { sequence = sequence + 1; } } public void TestSingleton () { ThreadPool.QueueUserWorkItem(new WaitCallback(CreateSingleton)); ThreadPool.QueueUserWorkItem(new WaitCallback(CreateSingleton)); } public void CreateSingleton(object o) { SingletonNotThreadSafeConsuming instance = SingletonNotThreadSafeConsuming.Instance(); instance.GetResource(); } posted on 2005-09-13 19:02:00 by microhelper 评论(8) 阅读(4941) Design.Patterns.Step.By.Step.2Template Method使用了对象继承,而继承是一种很强的对象和对象之间的耦合关系,底层模块还是依赖于高层模块,比如子类要知道哪些abstract method要重写,哪些hook method可以做扩展,哪些基类资源可以利用。 strategy模式使用对象之间的组合关系来代替继承,进一步减弱高层模块和底层模块之间的依赖,让底层独立于高层,使其完全符合更符合DIP的原则, 这样底层代码不需要了解高层代码是怎么工作的,高层也不需要知道底层的实现细节, 相对于Template Method模式来说strategy模式革命的更彻底一些。 还拿Report来作一个简单的例子。 Report的输出可以是Html格式的,可以是Word格式的,也可以是PDF格式的,我们可以定义一个Interface:IReportPublisher,在IReportPublisher中定义高层模块和低层模块之间的调用协议。(或者说Contract) Interface IReportPublisher {public void Publish()} HTMLReportPublisher : IReportPublisher WordReportPublisher : IReportPublisher PDFReportPublisher : IReportPublisher Report { Public void GenerateReport() { … reportPublisher = MyContext.GetService(…) reportPublisher.Publish(reportData) … } } 当然实现strategy模式也有代价,将Template Method改造成strategy模式后,架构中层次变复杂了,一些Template Method模式原有的特性就没有办法利用了,比如子类可以调用基类一些资源。 应用任何一种模式都会有代价,学习模式时,明白为什么这么做比明白怎么实现更重要,了解模式带来的收益的同时也要了解你要付出的代价。模式也是一直随着技术的发展在发展的,有些模式在慢慢消亡,有些新的模式出现,有些模式被新的编程语言天然支持,有些模式的形式发生了变化,Gof的《设计模式》里的一些观点现在来说已经是有些过时了。 strategy模式和Template Method模式的对比还体现了面向对象的另一个思想,解决对象之间的协作问题应用对象组合优先于对象继承。在面向对象的初期,人们非常看重对象继承,继承一个类,就可以重用该类的代码,把很多类的代码抽取到一个基类中就可以去掉代码重复,创建一个子类,改变一点点就能创造出一个能实现新功能的类出来,通过继承我们可以建立完整的软件结构分类,每一层都可以重用该层以上的代码,这看起来很美好,到后来人们才慢慢发现继承非常容易被过度使用,而过度使用带来的收益比代价要高的多,所以我们减少对继承的使用,用组合和委托来代替继承。 strategy模式和Template Method模式都面对一个问题,在运行时怎么创建某个子类或者某个实现了某个interface的类的实例,那就涉及关于创建对象实例的模式:Singleton模式和Factory模式。 posted on 2005-09-12 18:03:00 by microhelper 评论(0) 阅读(4294) Design Patterns Step By Step.1template method模式和strategy模式 template method模式和strategy模式都是关注对象的行为的,按照依赖倒置的方法来分离抽象和具体的实现,但是两者的实现方法不同。template method模式应用了面向对象中继承的思想,而strategy模式则应用了委托的思想,从template method模式和strategy模式中也可以看到面向对象世界中abstract类和interface的异同。实际上这两种模式我们经常会用到,只是可能没有意识到而已。 Template method的常见用法是将运算的骨架放在基类中,然后将某些具体的算法放到子类里面实现,这样就可以使得子类不改变算法的结构即可重定义该算法的某些特定步骤。 Template method的一个例子:Report服务。 假定系统中有一系列Report,Booking Report, Billing Report, Aging Report…。这些Report参数不一样,界面不一样,逻辑不一样,但是也有一些有共同点,验证权限,结果输出,Report载入步骤等等。那么为了避免重复代码,有一个较好的可扩充的结构,我们把这些共同点extract到一个基类中ReportBase,简单示例如下: public class ReportBase { public void OpenReport(string reportId) { if(UserIsInRole()==true) { Initialize(); LoadSavedReport(); } } private void Initialize() { InitializeControl(); SetDefaultValue(); } protected abstract void InitializeControl() { } protected abstract void LoadSavedReport () { } { } }
ReportBase.OpenReport()是一个Template,定义了算法的每一步,并且允许子类提供其中某些步的具体实现。 我们可以看到Template Method的主要特点是,将各个子类中不变的行为提取到基类中实现,可变的部分留给子类自己实现,而且基类中定义了一个相对稳定的结构,也就是一个模版Template,模版中的某些步骤留待子类来实现,基类还可以控制子类的扩展,允许某些子类在某些点上作扩展。对于基类来说意义在于控制整个结构,减少重复代码,对于子类来说意义在于不改变算法的机构可以方便的提供一种实现。 从Template Method中可以看到Framework和控制反转的精神,不是每个具体做事情的子类调用所需的Library完成某个行为,而是提供具体实现,让高层的代码来调用。 (Hollywood Principle: 当高层的模块依赖低层的模块时,由高层的模块决定何时以及如何调用底层模块,也就是说高层模块对底层模块讲:Don’t call me, we’ll call you) 当然Template Method模式和strategy模式在现在看来都已经是很自然的都东西。 应用Template Method需要先对代码逻辑作分析,哪些放到基类,哪些留给子类,当然这属于OO世界最基本的东西。如果现有的代码重构到Template Method可以参考《Refactoring》Dealing with Generalization一章。 应用Template Method需要注意的是基类需要指明那些行为是子类必须重定义的,哪些行为是允许子类重定义的(Abstract method和Hook Method),具体到C#的语法就是abstract和virtual定义。而且需要仔细评估那些子类必须重定义的行为,避免子类中需要做过多的重定义工作。对于可以允许子类重定义的行为来说好比提供了一个hook,在基类中通常是一个空操作,允许子类在这一点上扩展基类的行为。 另外一点需要注意的是继承属于很强的耦合关系,过多的继承关系会使系统变得僵化难以变化,往往会用对象的组合来代替继承。 一个替代继承的模式是strategy模式。 参考 《Head.First.Design.Patterns].Head.First.Design.Patterns》 《敏捷软件开发 原则、模式与实践》 posted on 2005-09-09 13:06:00 by microhelper 评论(5) 阅读(4502) |
||
|
Powered by: Joycode.MVC引擎 0.5.2.0 Copyright © MicroHelper.Net |
||