设计模式 学习笔记(5)迪米特法则、外观模式、建造者模式
(11)迪米特法则
迪米特法则(LoD)也叫最少知识原则。如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
迪米特法则首先强调的前提是在类的结构设计上,每一个类都应当尽量降低成员的访问权限,,也就说一个字段或行为若不需要别的类知道就不用公开,包装好自己的private状态。需要公开的话就用属性来实现。
迪米特法则其根本思想,是强调了类之间的松耦合。类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。也就是说,信息的隐藏促进了软件的复用。
(12)外观模式
外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
1 class SubSystemOne 2 { 3 public void MethodOne() 4 { 5 Console.WriteLine("子系统方法一"); 6 } 7 } 8 9 class SubSystemTwo 10 { 11 public void MethodTwo() 12 { 13 Console.WriteLine("子系统方法二"); 14 } 15 } 16 17 class SubSystemThree 18 { 19 public void MethodThree() 20 { 21 Console.WriteLine("子系统方法三"); 22 } 23 }
外观类 //外观类,需要知道所有的子系统的方法或属性,进行组合,以备外界调用
1 class Facade 2 { 3 SubSystemOne one; 4 SubSystemTwo two; 5 SubSystemThree three; 6 7 public Facade() 8 { 9 one=new SubSystemOne(); 10 two=new SubSystemTwo two(); 11 three=new SubSystemThree(); 12 } 13 14 public void MethodA() 15 { 16 Console.WriteLine("\n方法组A()----"); 17 one.MethodOne(); 18 two.MethodTwo(); 19 } 20 21 public void MethodB() 22 { 23 Console.WriteLine("\n F方法组B()----"); 24 two.MethodTwo(); 25 three.MethodThree(); 26 } 27 }
客户端调用 //由于Facade的作用,客户端可以根本不知三个子系统类的存在
1 static void Main(string[] args) 2 { 3 Facade facade=new Facade(); 4 facade.MethodA(); 5 facade.MethodB(); 6 Console.Read(); 7 }
外观模式在以下三个阶段使用最好。首先,在设计初期阶段,应该要有意识的将不同的两个层分离,比如经典的三层架构,就需要考虑在数据访问层和业务逻辑层、业务逻辑层和表示层的曾与层之间建立外观Facade,这样可以为复杂的子系统提供一个简单的接口,使得耦合大大降低。其次,在开发阶段,子系统往往因为不断地重构演化而变得越来越复杂,大多数的模式使用时也都会产生很多很小的类,这本是好事,但也给外部调用它们的用户程序带来了使用上的困难,增加外功Facade可以提供一个简单的接口,减少他们之间的依赖。第三,在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须要依赖它。此时用外观模式Facade也是非常合适的。你可以为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade与遗留代码交互所有复杂工作。
(13)建造者模式
建造者模式(Builder),将一个复杂对象的构件与它的表示分离,使得同样的构建过程可以创建不同的表示。如果你需要讲一个复杂对象的构建与它的不是分离,使得同样的构建过程可以创建不同的表示的意图时,我们需要建造者模式,又叫生成器模式。建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。如果我们用了建造者模式,那么用户就只需指定需要建造的类型就可以得到它们,而具体建造的过程和细节就不需知道啦。
Product类——产品类,由多个部件组成。
1 class Product 2 { 3 IList<string> parts=new List<string>(); 4 public void Add(string part)//添加部件产品 5 { 6 parts.Add(part); 7 } 8 public void show() 9 { 10 Console.WriteLine("\n产品 创建----"); 11 foreach (string part in parts) 12 { 13 Console.WriteLine(part); 14 } 15 } 16 }
Builder类——抽象建造者类,确定产品由两个部件PartA和PartB组成,并声明一个得到产品建造后结果的方法GetResult。
1 abstract class Builder 2 { 3 public abstract void BuildPartA(); 4 public abstract void BuildPartB(); 5 public abstract Product GetResule(); 6 }
ConcreteBuilder1类——具体建造这类
1 class ConcreteBuilder1:Builder 2 { 3 private Product product=new Product(); 4 public override void BuildPartA() 5 { 6 product.Add("添加部件A"); 7 } 8 public override void BuildPartB() 9 { 10 product.Add("部件B"); 11 } 12 public override Product GetResult() 13 { 14 return product; 15 } 16 }
Director类——指挥者类
1 class Director 2 { 3 public void Construct(Builder builder) 4 { 5 builder.BuildPartA(); 6 builder.BuildPartB(); 7 } 8 }
客户端代码,客户不需知道具体的建造过程。
1 static void Main(string[] args) 2 { 3 Director director=new Director(); 4 Builder b1=new ConcreteBuilder1(); 5 Builder b2=new ConcreteBuileder2(); 6 director.Construct(b1); 7 Product p1=b1.GetResult(); 8 p1.Show(); 9 director.Construct(b2); 10 Product p2=b2.GetResult();//指挥者用ConcreteBuilder2的方法来建造产品 11 p2.Show(); 12 Console.Read(); 13 }
所以说建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时适用的模式。