- 浏览: 318496 次
- 性别:
- 来自: 长沙
文章分类
最新评论
-
完善自我:
支持一下!
揭秘IT人才特点:中美印日四国程序员比较 -
悲剧了:
好文,看玩thinking in java的提到的异常处理,看 ...
高效的Java异常处理框架(转) -
yin_bp:
开源框架bbossgroups页支持组件异步方法调用哦,详情请 ...
Spring 3中异步方法调用 -
flyjava:
sun的悲哀
Apache怒了,威胁说要离开JCP
深入探讨超越设计模式之外的设计原则
简介: 可复用面向对象软件的基础 -- 设计模式,以其可复用的设计初衷、精巧的逻辑思维被广大面向对象程序设计所追捧。但不少程序设计者却经常将思考的问题转换为遇到了什么场景就要用什么模 式。这种八股文式的思维在某种程度上严重影响了程序设计的艺术性,并固化了程序设计者的思想,违背了设计模式的初衷。在本文中,作者总结了设计模式背后的 核心思想,并提出了几个关键的设计原则,例如面向接口、封装变化、依赖倒置原则、只和朋友交谈等。程序设计者只需在程序设计时遵循这些原则,便会发现原来 已经在使用某些设计模式了。
GOF 的设计模式推出以后,受到程序员的热烈追捧,很多程序员不亦乐乎的埋头苦读甚至背诵其 23 个设计模式,并以熟悉设计模式而自豪。然而,在实际的程序设计中,很多程序员并未能把设计模式应用到自己的场景中。原因有很多,设计模式太多以至于常常被 混淆;设计模式应用场景太局限或者程序员自己意识不到应用的场景。综合各种原因,根本原因只有一个,程序员并不能透彻理解,熟练应用设计模式的核心思想。 笔者认为,设计模式并不是条条框框,设计模式也不是简单的 23 种。设计模式体现的一种思想是:尽可能的复用,而实现可复用的手段无外乎笔者总结的几个设计原则而已。
彻底的忘掉 GOF 的设计模式吧,程序设计应该是一门艺术,而不是备受束缚的那些模式。
该原则的核心思想是,在程序设计中找出应用中可能需要变化之处,把它们独立出来以便以后可以轻易的改动或者扩充,而不影响不需要变化的部分。 事实上如果您回过头去重新阅读设计模式的书籍,您会发现,封装变化几乎是每个设计模式背后的精神所在。所有的模式都提供了一套方法让系统中的某部分改变不 会影响其它部分。
我们举一个简单的例子,我们建立一个 Car 的基类,有两个继承类 Benz 和 BMW, 具体参见下图 1:
相信大部分人都会这么设计,但是这个设计有什么问题呢?我们看待问题需要以发展的眼光,假如科技发展了,所有的 Car 都可以飞了,怎么办?有人说,很简单,给 Car 加一个 protected 的 fly() 方法,这样 Benz 和 BMW 就都可以飞了,继承真伟大!好,那么如果我需要建立另外一个 Car 的子类玩具车(Toycar), 我们知道玩具车可以 run, 但不能 fly 的。怎么办?还是好办,我们可以重载玩具车的 fly 方法,让他们什么都不干。那好,又一个子类来了,模型车(ModelCar)。模型车不能 run,不能 fly,好办,继续重载他们的这些方法。见下图 2:
如果我们有更多的 Car 的子类呢?有没有觉得有点繁琐,是的,我们需要重载太多的方法了。
继承并不能帮我们解决问题 !
可不可以使用接口,我们可以把 fly 从超类中取出来,分别作为接口,Flyable,这样一来只有 Benz 和 BMW 才实现 Flyable 接口,ToyCar 和 modelCar 并不实现该接口。Run 也作类似处理。见下图 3:
大家可以看到,这其实是一个很笨的办法,除去 description() 方法,我们使用继承需要重载 3 个方法,可是我们使用接口实现则需要额外定义两个接口类和5个方法。接口方法里面并不能有实现代码,而 ToyCar 的 fly 行为和 Benz 的飞行行为也可能不尽相同,那么这就意味着我们需要实现越来越多的 fly() 方法。
接口也不行!
怎么办?想一想我们的前面提到的设计原则,把变化的和不变化的分离开来,以便我们以后可以轻易的改动和扩充,而不影响其它不需要变化的部分。 我们变化的部分是什么?是否可以飞行,是否可以 run,以何种方式飞行?何种方式 run ? Benz,BMW 和 ToyCar 的飞行行为和 run 行为各不相同。我们可以把这些不同的 fly 和 run 抽象出来。见如下图 4:
看到这,也许您应该大概明白接下来应该怎么办了。是的,很简单,我们可以给 Car 类加入飞行行为和 run 行为的实例变量。而在初始化 Car 的子类时传入的具体行为进行初始化,这样每个子类就自然拥有了相应的行为。
代码参见如下:
public abstract class Car { protected RunBehavior runBehavior; protected FlyBehaviro flyBehavior; public abstract description (); protected performFly() { flyBehavior.fly(); } protected performRun() { runBehavior.run(); } } public class Benz extends Car { public String description() { System.out.println(“I am Benz!”); } public Benz() { this.runBehavior = new HighSpeedRunBehavior(); this.flyBehavior = new HighFlyingBehavior(); } } |
上述代码中我们实现了 Benz,如果我们要实现 ToyCar,一个不能飞,但可以跑。尝试一下,看看多简单。
public class ToyCar extends Car { public String description() { System.out.println(“I am Toy car!”); } public Benz() { this.runBehavior = new LowSpeedRunBehavior(); this.flyBehavior = new NoFlyingBehavior(); } } |
- 回过头来,看看我们前面所作的工作,第一个我要告诉您的是,恭喜您学会了策略模式,上面我们的设计的核心实现就是使用了策略模式。
- 继承和接口不能解决一切问题,尽量的利用组合将为您的设计带来低耦合。
- 尽可能的针对接口或者抽象类而不是实现去编程,试想,如果我们定义的 Car 类组合具体的行为类,也就是实现,那么它就被绑死了,我们不可能以后再改变它的行为。但这样,我们可以在运行时动态的改变 Car 子类的具体行为。这也是我们成功的关键。
- 最重要的,把变化的和不变化的分离出来,封装变化的部分以应对随时改变。
继续我们的话题,假设我们有一家汽车公司,可以生产 Benz、BMW、ToyCar 和 ModelCar(姑且这么认为吧,虽然这不太符合常理),那么该如何设计我们的实现呢?很简单,参见下面代码:
public class CarCompany { public CarCompany () { } public Car produce(String type) { Car car = null; if(“Benz”.equals(type)) { car = new Benz(); } else if(“BMW”.equals(type)) { car = new BMW(); } else if(“ToyCar”.equals(type)) { car = new ToyCar(); } else if(“ModelCar”.equals(type)) { car = new ModelCar(); } else { } car.assembly(); // 组装 car.sprayPainting(); // 喷漆 car.proof(); // 校对 return car; } } |
老问题,上面的代码有问题么?但从业务逻辑上讲,当然没问题。可是还是要用变化的眼光看问题,上面的代码维护起来成本很高。上面的代码要求我 们无论是 Benz、BMW、ToyCar 还是 ModelCar 都不能在将来发生变化。否则,我们这段代码就有维护的成本和风险。
有没有更有效的办法,想想我们第一个设计原则:把变化的部分提出去,变化的部分是什么,显然生成 car 的那一段。我们把它提出去,参见下面代码:
清单 4. CarFactory 和 CarCompany 另一种实现
public class CarFactory { public CarFactory () { } public Car createCar(String type) { Car car = null; if(“Benz”.equals(type)) { car = new Benz(); } else if(“BMW”.equals(type)) { car = new BMW(); } else if(“ToyCar”.equals(type)) { car = new ToyCar(); } else if(“ModelCar”.equals(type)) { car = new ModelCar(); } else { } return car; } } public class CarCompany { CarFactory carFactory; public CarCompany (CarFactory carFactory) { this.carFactory = carFactory; } public Car produce(String type) { Car car = null; Car = carFactory.createCar(type); car.assembly(); // 组装 car.sprayPainting(); // 喷漆 car.proof(); // 校对 return car; } } |
很显然,我们的 CarCompany 现在只依赖 CarFactory 一个类了。有人说这么做有什么用,我们只不过把问题转移到另外一个对象 CarFactory 了,问题依然存在。但是别忘了,我们的 CarCompany 可能不止一个 produce() 方法。它可能还有 sale(), repair() 方法。这样,我们相当于是把几个问题缩小为一个问题了。
- 这个例子虽然很简单,但是却告诉我们一条最重要的设计原则,一个类应该尽可能少的与其它类产生联系,尽可能的保持类之间的耦合度,保持类的最少知识量。
- 恭喜您,您学会了简单工厂模式。
- 外观模式也是对本原则的典型应用。具体请参见设计模式相关书籍。
在您的设计里面,一定要减少对具体类的依赖,尽量依赖抽象,不要依赖具体类。这就是依赖倒置原则。
听起来有点像面向接口,不针对实现编程。的确很类似,但是这里强调的是抽象。具体说来就是不要让高层组件依赖低层组件,而且不管高层低层组件,都应该依赖抽象。高层组件最多是依赖低层组件的抽象。低层的抽象和实现也只依赖于高层的抽象。
所谓高层组件是由其它低层组件定义其行为的类。高层组件是包含重要的业务模型和策略选择,低层模块则是不同业务和策略实现。
也许您不是很理解这段话的含义。不要紧,继续我们上面的例子。假设随着汽车公司规模越来越大,业务规模拓展到了亚洲和欧洲。我们希望可以针对 亚洲人和欧洲人生产出不同的同一品牌的的汽车。比如同一品牌 BMW 亚洲是左驾驶座(当然除了一些特殊地区),欧洲是右驾驶座。看看下面的实现。
public class DependencyCarCompany { public CarCompany () { } public Car produce(String style, String type) { Car car = null; if(“Asia”.equals(style)) { if(“Benz”.equals(type)) { car = new AsiaBenz(); } else if(“BMW”.equals(type)) { car = new AsiaBMW(); } else if(“ToyCar”.equals(type)) { car = new AsiaToyCar(); } else if(“ModelCar”.equals(type)) { car = new AsiaModelCar(); } else { } } else if(“Europe”.equals(style)) { if(“Benz”.equals(type)) { car = new EuropeBenz(); } else if(“BMW”.equals(type)) { car = new EuropeBMW(); } else if(“ToyCar”.equals(type)) { car = new EuropeToyCar(); } else if(“ModelCar”.equals(type)) { car = new EuropeModelCar(); } else { } car.assembly(); // 组装 car.sprayPainting(); // 喷漆 car.proof(); // 校对 return car; } } } |
够简单吧!总结它们对象之间依赖的情况如图 5 所示:
我们发现 CarComany 依赖的具体类有 8 个,如果任何一个类发生改变,CarCompany 都需要改变。这至少不符合我们的原则二:只和朋友交谈。应用我原则一,把变化的部分提出来。我们可以定义两个 CarCompany 的子类:AsiaCarCompany 和 EuropeCarCompany 用来生产不同样式的同一品牌的汽车。在这两个子类里面,需要做的就是生成不同品牌和样式的汽车,然后再调用超类的三个方法。这样的话我们可以把生成汽车的 方法提出来。
public abstract class CarCompany { public Car produce(String type) { Car car = createCar(type); car.assembly(); // 组装 car.sprayPainting(); // 喷漆 car.proof(); // 校对 return car; } protected abstract Car createCar(String type); } public class AsiaCarCompany { protected Car createCar(Sting type) { Car car = null; if(“Benz”.equals(type)) { car = new AsiaBenz(); } else if(“BMW”.equals(type)) { car = new AsiaBMW(); } else if(“ToyCar”.equals(type)) { car = new AsiaToyCar(); } else if(“ModelCar”.equals(type)) { car = new AsiaModelCar(); } else { } return car; } } public class EuropeCarCompany { protected Car createCar(Sting type) { Car car = null; if(“Benz”.equals(type)) { car = new EuropeBenz(); } else if(“BMW”.equals(type)) { car = new EuropeBMW(); } else if(“ToyCar”.equals(type)) { car = new EuropeToyCar(); } else if(“ModelCar”.equals(type)) { car = new EuropeModelCar(); } else { } return car; } } |
DependencyCarCompany 的问题在于,它依赖于每一个具体的 Car 类型。然而,在应用第二种方法后,CarCompany 现在只依赖 Car 类型的抽象,不再依赖具体类型,而是把这些依赖转移到子类中。我们可以画一个对象依赖图 6:
从这个图中我们可以看出:
- 我们的高层组件也就是 CarCompany 已经由原来的 8 个低层对象依赖变化为只依赖一个低层对象的抽象 Car。这就是依赖抽象。
- 对比上面两个图,您会发现,以前所绘制的依赖是自上而下,而现在则是倒置过来。高层和低层组件都依赖于抽象的 Car。这就是依赖的倒置。
工厂方法模式定义
定义一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法让类的实例化推迟到的子类。
- 恭喜您,您学会了工厂方法模式。上面的例子实际上是工厂方法的一个典型应用。
- 一些辅助原则可以帮助您更好的运用 DIP:
- 任何变量都不应该持有一个指向具体类的引用。
- 任何类都不应该从具体类派生,而是派生一个抽象类。
- 任何方法都不应该覆盖它的任何基类中已经实现了的方法。
继续刚才的例子,随着汽车公司业务越来越大,为了满足不同客户的不同需求,对于任一品牌的汽车我们将有不同型号的配置。我们的配置包括气囊 (Balloon)、天窗(SkyLight)以及自动加热座椅(HeatedSeats)等。每款汽车的价格为汽车自身价值加上配件的价格。设计如下图 7:
Oh, My God! 这是什么?类爆炸?!好可怕的一件事。可以想象出来,这样的设计将来的维护成本又多高。假如我想增加新的配件怎么办,假如我想增加新的品牌又怎么办?
其实我们可以用实例变量和继承来重构上面的设计。见下图 8:
我们在超类 Car 里面 cost() 方法计算各种配件的价格,然后在子类里面覆盖 cost() 方法,但是会调用超类 cost 方法得到配件价格和,然后再加上子类汽车的基本价格。
public abstract class Car { protected Balloon balloon; protected SkyLight skyLight; protected HeatedSeat heatedSeat; protected int cost() { int res = 0; if(hasBalloon) { res += 25000; } if(hasSkyLight) { res += 20000; } if(hasHeatedSeat) { res +=10000; } } void setBalloon(Balloon balloon); boolean hasBalloon(); …. …. } public Benz extends Car { public Benz(Balloon blloon) { this.setBalloon(balloon); } public int cost() { int res= 1000000; res += super.cost(); } } |
怎么样?看起来好像天衣无缝的解决了我们的问题。然而有下面几个问题需要考虑:
- 如果配件的价格发生改变怎么办?
- 如果出现新的配件怎么办?
- 如果某些配件在某种品牌汽车上不能应用怎么办?比如您在玩具车上装 ABS(自动刹车系统)显然是没有意义的。
- 如果我想给我的车安装 4 个气囊而不是一个两个,怎么办?
为什么看起来完美的设计,会有这么多解决不了的问题? 因为它违背我们的设计原则:类应该对扩展开放,对修改关闭。我们的目标是允许类容易扩展。在不修改现有代码的基础上,就可以搭配新的行为。这样设计才可以接受新的功能来应对改变的需求。
该原则最典型的应用就是装饰模式。让我们以装饰模式的思想重构我们上面的实现。
- 首先用户需要一辆汽车。那我们就构造一辆裸车,并计算价格。
- 用户希望是 BMW, 那我们就把它封装为 BMW,并计算价格。
- 用户希望带有气囊,那我们就给我们的 BMW 装饰上气囊,并加上气囊的价格 25000。
- 用户希望有天窗,那我们就给我们的 BMW 装饰上天窗,并加上气囊的价格 20000。
- 用户希望有加热椅,那我们就给我们的 BMW 装饰上加热椅,并加上的价格 10000。
- 用户希望带有双重气囊,那我们就给我们的 BMW 再装饰上气囊,并加上气囊的价格 25000。
见图 9:
参见我们的实现代码。
public abstract class Car { protected abstract int cost(); } public class Benz extends Car { public int cost() { return 100000; } } public abstract class CarDecorator extends Car { protected abstract int cost(); } public class Balloon extends CarDecorator { public Car car; public Balloon(Car car) { this.car = car; } public int cost() { return car.cost() + 25000; } } public class SkyLight extends CarDecorator { public Car car; public SkyLight (Car car) { this.car = car; } public int cost() { return car.cost() + 20000; } } public class HeatedSeat extends CarDecorator { public Car car; public HeatedSeat (Car car) { this.car = car; } public int cost() { return car.cost(0 + 10000; } } |
下面看看我们的测试类。
public class CarWithDecorator { public static void mian(String[] args) { Car car = new BMW(); car = new Balloon(car); car = new SkyLight(car); car = new HeatedSeat(car); car = new Balloon(car); System.out.println(car.cost()); } ... } |
怎么样?回过头,想一想我们前面提出的那四个问题,是用这种设计方式是不是可以很好地解决呢?
- 恭喜您,您学会了装饰模式。
- 现实世界中,装饰模式,也即我们面向扩展开放,面向修改关闭的应用很多。最常见的就是 Java I/O。见下图 10:
图 10. Java I/O
- 应用开放封闭原则,有时候会带来小类过多的情况,这是这个原则所带来的潜在问题。所以在实际应用中也要注意设计上的考虑。而不要一味的遵循。
设计原则不是统一的,不同人对有不同的设计原则有不同的见解,设计原则也不限于上面所陈述的几点。然后设计原则大的方向是统一的,那就是让代 码尽可能的应对变化,尽可能的可复用。设计模式不是万能的,没有设计模式也不是不能的。然而在程序设计过程中遵循一些最基本的设计原则则是一个优秀的程序 员所必需的,良好的设计原则的应用可以让您设计的程序从容应对可能的改变,可以让您的代码变得优雅而富有艺术性。
学习
-
参考 设计模式概述
,了解设计模式基本内容。
-
查看教程“Java 设计模式 101
”,了解设计模式基本词汇以及简单使用设计模式。
-
查看教程“Java 设计模式 201:超越四人组
”,了解设计模式深层次的应用。
-
查看系列文章“从 Java 类库看设计模式
”,了解 JDK 在设计模式中的应用。
-
技术书店
:浏览关于这些和其他技术主题的图书。
- developerWorks Java 技术专区 :数百篇关于 Java 编程各个方面的文章。
原文:http://www.ibm.com/developerworks/cn/java/j-lo-beyondpattern/?ca=drs-tp4608
发表评论
-
Qi4j和NoSql运动
2010-11-16 23:00 162524日一篇Qi4j and the NoSQL ... -
Threaded vs Evented Servers
2010-11-16 22:48 955Threaded vs Evented Servers ... -
BASE: An Acid Alternative
2010-11-16 21:13 983In partitioned databases, tra ... -
eBay 的Scalability最佳实践
2010-11-16 20:52 930用什么来衡量一天没 ... -
Scalability Best Practices: Lessons from eBay
2010-11-16 20:45 874At eBay, one of the primary a ... -
SmugMug 的架构介绍
2010-11-16 20:36 899本文介绍的 SmugMug 是一家提供付费图片 ... -
来自淘宝的架构经验
2010-11-16 18:07 1248日前参加了一场淘宝网 架构师黄裳带来的技术分享,在最后他 ... -
可伸缩性最佳实战
2010-11-16 17:50 607异步 同步调用使得组件和组件之间紧密耦合起来,这样就使得 ... -
伸缩性和可用性反模式
2010-11-16 17:48 740这篇文章讲了伸缩性 和可用性方面的反模式,也按照自己的理 ... -
使用qi4j实现DCI架构
2010-11-16 17:24 2933我曾经DCI架构是什么? 在一文中提到Qi4j框架实现DCI ... -
DCI架构是什么?
2010-11-16 17:07 2050DCI是数据Data 场景Context 交互Interact ... -
纵向扩容 vs. 横向扩容
2010-11-02 09:58 5440该文原版著作权属于Malc ... -
云计算在电信应用中的思考
2010-11-01 17:59 971云计算是在网格(Grid)、效用(Utility)和 ... -
真正的线性可伸缩性需要新的模式和中间件架构吗?
2010-11-01 17:27 978在构建线性可收缩应用 ... -
性能与可伸缩性的概念及其关键影响因素
2010-11-01 17:22 1158性能与可伸缩性常常决定企业应用的成败,尤其在 ... -
构建的可伸缩性和达到的性能
2010-11-01 17:19 1007实现伸缩性和性能调优的经验所保有的价值容易被低估。两者都是“晚 ... -
可伸缩性的最差实践
2010-11-01 17:02 796引言 在扩展大量大型 ... -
可伸缩性,美妙的可伸缩性
2010-11-01 16:37 1439可伸缩性带来的好处 ... -
大型门户网站架构设计的可伸缩性
2010-11-01 16:34 910我们知道,对于一个大型门户网站来说,可伸缩性是非常重要的,怎么 ... -
可伸缩性设计
2010-11-01 16:27 1012好的设计是实现高度可 ...
相关推荐
《超越设计模式:软件开发的艺术》 设计模式作为软件开发中的重要工具,旨在提升代码的复用性和可维护性,但过度依赖特定模式可能导致思维固化。实际上,设计模式的本质是抽象出可复用的设计原则,而非固定不变的...
### 软件架构与设计模式:深入理解与实践 ...侯捷的教材不仅介绍了设计模式的基本概念和GOF设计模式,还探讨了超越GOF的模式以及设计模式在具体编程语言中的应用,是一本值得深入学习和研究的宝贵资料。
这门课程涵盖了设计模式的基本原理、GoF的设计模式以及超越GoF之外的一些设计模式。 ### 二、设计模式的应用与实践 #### 1. GoF设计模式的实践 - **GoF设计模式**主要包括创建型模式、结构型模式和行为型模式三大...
侯捷的课件还讨论了超越GoF的设计模式,如引用计数(Reference Counting)、池化分配(Pooled Allocation)、在Java中的可撤销(Undoable)等。这些模式专注于解决更现代的编程挑战。 课件深入解析了在C++和Java中...
Java设计模式是软件工程中的一种最佳实践,它提供了一种在特定情况下解决常见问题的标准化方法。这个"Java设计模式(chm版)"资源很可能包含了一份详细解释各种设计模式的电子书,主要关注Java语言中的应用。设计...
深度学习的教学设计模式是一系列旨在通过分析教学内容、设计教学活动,以促进学生深度思考和学习的教学策略。东北师范大学教授马云鹏提出,在深度学习模式中,首先需要确定学习单元,这个单元可以是教材中的一个单元...
#### 设计模式的介入:超越继承的解决方案 面对继承带来的局限性和问题,设计模式提供了一系列优雅的解决方案。在本章节中,我们重点关注以下几点: 1. **封装行为**:通过将行为封装在独立的类中,而非直接在Duck...
豪尔赫·阿朗戈 Jorge Arango 拥有20年的信息架构环境设计经验,并且担任IA协会的总裁兼董事长。 目录 · · · · · · 前言 xvii 第1部分信息架构简介 第1章信息架构要解决的问题 3 你好,iTunes 5 信息架构要...
4. 创新思维:优秀的设计师能够以创新的视角来解决问题,设计出独特的LOGO,这往往需要跳出常规的思维模式。 5. 项目管理:管理时间和资源的能力对设计师来说同样重要。一个优秀的设计师能够有效地规划项目时间表,...
- 对象母亲模式是一种在Java中用于简化具有特定配置的对象创建的设计模式,特别是用于测试。与其为每个测试用例手动构建具有不同属性的对象,不如创建一个专用的“对象母亲”类或方法,该方法以预定义的设置生成...
《信息架构:超越Web设计(第4版)(全彩)》 的前三个版本都是信息架构领域的开山著作。其中描述了信息组织的普遍和永恒原则,这一原则也适用于不断增长的移动世界。在第4版中,作者运用大量最新的插图和例子为这些...
《信息架构:超越Web设计(第4版)》是一本由[美]Louis Rosenfeld编著的专业书籍,专注于探讨信息架构在数字环境中的应用和发展。信息架构是构建和组织网络内容,使其易于理解和导航的关键领域,它涉及到用户体验...
超越5000在硬件设计上考虑了多种保护措施,如过载保护、芯片插反保护、短路保护以及软写入模式,提高了设备的稳定性和安全性。通过3个微动开关来选择编程电压,简化了操作流程,无需记忆复杂的跳线设置。 #### 软件...
在这样的背景下,“超越传统模式-自主实施信息化管理”提出了一种新的企业信息化模式。自主实施信息化的核心原理是企业可以通过快速开发平台自我实施信息化,不需要依赖成品软件的固定功能,也不需要承担自行开发的...
文章以管理控制系统的(Management Control Systems,MCSs)设计原则变化为切入点,基于实施超越预算思想对管理层决策行为的影响。 在管理会计领域,超越预算是一个相对较新的概念,它挑战了传统的预算制度,认为...
本文档是一篇关于软件设计模式深入探讨的内容,其关注点超越了经典的《设计模式:可复用面向对象软件的基础》(也称为Gang of Four,GoF)一书中描述的23个设计模式。本文档的作者是Kevlin Henney和Frank Buschmann...
它不仅在技术上进行了革新,更在理念上提出了开放的电脑教学模式,为教学和管理提供了更加灵活和高效的方式。其核心优势体现在对机房多样化需求的应对能力、强化的网络安全保护以及对操作系统的高效管理上。 首先,...
技术分析工具包括图表、指标和模式识别,这些工具帮助交易者识别市场趋势、支撑和阻力水平以及潜在的价格变动。 ### 交易系统的设计与开发 接下来,《超越技术分析》详尽地探讨了交易系统的构建过程。交易系统是一...