《专题:设计模式(精华篇)》 |
版本 |
作者 |
参与者 |
完成日期 |
备注 |
DesignPatterns_Classics_V01_1.0 |
严立钻 |
|
2018.07.31 |
|
|
|
|
|
|
##《专题:设计模式(精华篇)》发布说明:
++++在2018年4月7日,立钻哥哥发布了一篇《设计模式简单整理》(https://blog.csdn.net/vrunsoftyanlz/article/details/79839641),这里非常详细地整理出了设计模式的各种场景,现在立钻哥哥发布的是《专题:设计模式(精华篇)》,这是一种尝试:以简明扼要的方式来总结这些问题,这里以“专题”的形式来展现。
++++《专题:设计模式(精华篇)》将大幅度压缩篇幅,同时保留精华,以期达到精品之作。
++++设计模式简单整理:https://blog.csdn.net/vrunsoftyanlz/article/details/79839641
++++专题:设计模式(精华篇):https://blog.csdn.net/VRunSoftYanlz/article/details/81322678
##《专题:设计模式(精华篇)》目录:
#第一篇:设计原则
#第二篇:设计模式
#第三篇:模式大PK
#第四篇:立钻哥哥带您设计模式实战
#第一篇:设计原则 |
#第一篇:设计原则
++++1A.01、单一职责原则
++++1A.02、里氏替换原则
++++1A.03、依赖倒置原则
++++1A.04、接口隔离原则
++++1A.05、迪米特法则
++++1A.06、开放封闭原则
++SOLID设计原则:
++++立钻哥哥:软件设计最大的难题就是应对需求的变化,但是纷繁复杂的需求变化又是不可预料的。
++++我们要为不可预料的事情做好准备,这本身就是一件非常痛苦的情况,但是大师前辈们还是给我们提出了非常好的6大设计原则以及23个设计模式来“封装”未来的变化:
++++Single Responsibility Principle:单一职责原则;
++++Open Closed Principle:开闭原则;
++++Liskov Substitution Principle:里氏替换原则;
++++Law of Demeter:迪米特法则;
++++Interface Segregation Principle:接口隔离原则;
++++Dependence Inversion Principle:依赖倒置原则;
====>S、O、L、L、I、D:SOLID(solid,稳定的):建立稳定、灵活、健壮的设计,而开闭原则又是重中之重,是最基础的原则,是其他5大原则的精神领袖。
##1A.01、单一职责原则 |
++1A.01、单一职责原则(Single Responsibility Principle)
++++立钻哥哥:【单一职责原则(SRP)】:就一个类而言,应该仅有一个引起它变化的原因。
++++如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。(这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。)
++++对于单一职责原则,建议是接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。
++单一职责原则的好处:
++++1、类的复杂性降低:实现什么职责都有清晰明确的定义;
++++2、可读性提高:复杂性降低,那当然可读性提高了;
++++3、可维护性提高:可读性提高,那当然更容易维护了;
++++4、变更引起的风险降低:变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助;
##1A.02、里氏替换原则 |
++1A.02、里氏替换原则(Liskov Substitution Principle)
++++立钻哥哥:【里氏替换原则(LSP)】:子类型必须能够替换掉它们的父类型;
++++一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的区别。(也就是说:在软件里面,把父类替换成它的子类,程序的行为没有变化。)
++++只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。
++++采用里氏替换原则的目的就是:增强程序的健壮性,版本升级时可以保持非常好的兼容性。(即使增加子类,原有的子类还可以继续运行。)
++++在实际项目中:每个子类对应不同的业务含义,使用父类作为参数,传递不同的子类完成不同的业务逻辑,非常完美。
##1A.03、依赖倒置原则 |
++1A.03、依赖倒置原则(Dependence Inversion Principle)
++++立钻哥哥:【依赖倒置原则(DIP)】:高层模块不应该依赖低层模块,两个都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象;
++++在项目中,大家只要记住是:“面向接口编程”就基本上抓住了依赖倒置原则的核心。(依赖倒置原则是6大设计原则中最难实现的原则,它是实现开闭原则的重要途径,依赖倒置原则没有实现,就别想实现对扩展开放,对修改关闭。)
++依赖倒置原则包含三层含义:
++++A、高层模块不应该依赖低层模块,两者都应该依赖其抽象;
++++B、抽象不应该依赖细节;
++++C、细节应该依赖抽象;
++++补充1:抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是实现类,实现接口或继承抽象类而产生的类就是细节,其特点就是可以直接被实例化,也就是可以加上一个关键字new产生一个对象。
++依赖倒置原则的表现:
++++A、模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;
++++B、接口或抽象类不依赖于实现类;
++++C、实现类依赖接口或抽象类;
++++补充1:面向接口编程是OOD(Object-Oriented Design,面向对象设计)的精髓之一。
++依赖的三种写法:
++++第一种:构造函数传递依赖对象:
--在类中通过构造函数声明依赖对象,按照依赖注入的说法,这种方式叫做构造函数注入。
--public Driver(ICar _car){ this.car = _car; }
++++第二种:Setter方式传递依赖对象:
--在抽象中设置Setter方法声明依赖关系,依照依赖注入的说法,这是Setter依赖注入。
--public void SetCar(ICar car){ this.car = car; }
++++第三种:接口声明依赖对象:
--在接口的方法中声明依赖对象,采用接口声明依赖的方式,该方法也叫做接口注入。
--public void drive(ICar car);
##1A.04、接口隔离原则 |
++1A.04、接口隔离原则(Interface Segregation Principle)
++++立钻哥哥:【接口隔离原则(ISP)】:客户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上。
++++建立单一接口,不要建立臃肿庞大的接口。(接口尽量细化,同时接口中的方法尽量少)
++++接口隔离原则和单一职责原则的审视角度是不同的:单一职责要求的是类和接口职责单一,注重的是职责,这是业务逻辑上的划分;而接口隔离原则要求接口的方法尽量少。
++保证接口的纯洁性:
++++A、接口要尽量小。(这是接口隔离原则的核心定义,不出现臃肿的接口(Fat Interface),但是“小”是由限度的,首先就是不能违反单一职责原则。)
++++B、接口要高内聚。(高内聚就是提高接口、类、模块的处理能力,减少对外的交互。)(在接口中尽量少公布public方法,接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险也就越少,同时也有利于降低成本。)
##1A.05、迪米特法则 |
++1A.05、迪米特法则(Law of Demeter)
++++立钻哥哥:【迪米特法则(LoD)】:如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。(如果其中一个类需要调用另一个类的的某一个方法的话,可以通过第三者转发这个调用)
++++迪米特法则其根本思想是:强调了类之间的松耦合。(在类的结构设计上,每一个类都应当尽量降低成员的访问权限。)
++迪米特法则对类的低耦合包含以下4层含义:
++++A、只和朋友交流。(类与类之间的关系是建立在类间的,而不是方法间,因此一个方法尽量不引入一个类中不存在的对象。)(两个对象之间的耦合方式:组合、聚合、依赖等)
++++B、朋友间也是有距离的。(一个类公开的public属性或方法越多,修改时涉及的面也就越大,变更引起的风险扩散也就越大;)(尽量不要对外公布太多的public方法和非静态的public变量,尽量内敛,多使用private,protected等访问权限。)
++++C、是自己的就是自己的。(如果一个方法放在本类中,即不增加类间关系,也对本类不产生负面影响,就放置在本类中。)
++++D、谨慎使用Serializable。(从private变更为public,访问权限扩大了,如果服务器上没有做出相应的变更,就会报序列化失败。)
##1A.06、开放封闭原则 |
++1A.06、开放封闭原则(Open Closed Principle)
++++立钻哥哥:【开放-封闭原则(OCP)】:软件实体(类、模块、函数等等)应该可以扩展,但是不可修改。
++++对于扩展是开放的(Open for extension),对于更改是封闭的(Closed for modification)。
++++开放-封闭原则是面向对象设计的核心所在。
++如何使用开闭原则:
++++A、抽象约束。(抽象是对一组事物的通用描述,没有具体的实现,也就表示它可以有非常多的可能性,可以跟随需求的变化而变化。因此,通过接口或抽象类可以约束一组可能变化的行为,并且能够实现对扩展开放)
--第一:通过接口或抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法;
--第二:参数类型、引用对象尽量使用接口或者抽象类,而不是实现类;
--第三:抽象层尽量保持稳定,一旦确定即不允许修改;
++++B、元数据(metadata)控制模块行为。(尽量使用元数据来控制程序的行为,减少重复开发。)(元数据:用来描述环境和数据的数据,就是配置参数,参数可以从文件中获得,也可以从数据库中获得。)
++++C、封装变化。
--第一:将相同的变化封装到一个接口或抽象类中。
--第二:将不同的变化封装到不同的接口或抽象类中,不应该有两个不同的变化出现在同一个接口或抽象类中。
#第二篇:设计模式 |
#第二篇:设计模式
++++2B.01、单例模式
++++2B.02、工厂方法模式
++++2B.03、抽象工厂模式
++++2B.04、建造者模式
++++2B.05、原型模式
++++2B.06、适配器模式
++++2B.07、装饰模式
++++2B.08、桥接模式
++++2B.09、组合模式
++++2B.10、享元模式
++++2B.11、代理模式
++++2B.12、外观模式
++++2B.13、观察者模式
++++2B.14、模板方法模式
++++2B.15、命令模式
++++2B.16、状态模式
++++2B.17、职责链模式
++++2B.18、解释器模式
++++2B.19、中介者模式
++++2B.20、访问者模式
++++2B.21、策略模式
++++2B.22、备忘录模式
++++2B.23、迭代器模式
##2B.01、单例模式(Singleton) |
++2B.01、单例模式(Singleton)
++++立钻哥哥:【单例模式(Singleton)】:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
++++通常我们可以让一个全局变量使得一个对象被访问,但是不能防止实例化多个对象。(一个最好的方法就是:让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。)
++单例模式实现
++++立钻哥哥:Singleton类,定义一个GetInstance()操作,允许客户访问它的唯一实例,GetInstance()是一个静态方法,主要负责创建自己的唯一实例。
//立钻哥哥:Singleton类 class Singleton{ private static Singleton instance; private Singleton(){} //构造方法让其private,防止外界利用new实例化
//此方法是获得本类实例的唯一全局访问点 public static Singleton GetInstance(){ if(instance == null){ instance = new Singleton(); //不存在,new实例化一个 }
return instance; } //立钻哥哥:public static Singleton GetInstance(){} } //立钻哥哥:class Singleton{} |
##2B.02、工厂方法模式(Factory Method) |
++2B.02、工厂方法模式(Factory Method)
++++立钻哥哥:【工厂方法模式(Factory Method)】:定义一个用于创建对象的接口,让子类决定实例化哪一个类。(工厂方法使一个类的实例化延迟到其子类。)
++工厂方法模式实现
++++立钻哥哥:计算器的工厂方法模式实现
//立钻哥哥:计算器的工厂方法模式实现
//A、先构建一个工厂接口: interface IFactory{ Operation CreateOperation(); } //立钻哥哥:interface IFactory{}
//B、然后加减乘除各建一个具体工厂去实现这个接口: // //B.1、加法类工厂 class AddFactory : IFactory{ public Operation CreateOperation(){ return new OperationAdd(); } } //立钻哥哥:class AddFactory:IFactory{} // //B.2、减法类工厂 class SubFactory : IFactory{ public Operation CreateOperation(){ return new OperationSub(); } } //立钻哥哥:class SubFactory:IFactory{} // //B.3、乘法类工厂 class MulFactory : IFactory{ public Operation CreateOperation(){ return new OperationMul(); } } //立钻哥哥:class MulFactory:IFactory{} // //B.4、除法类工厂 class DivFactory : IFactory{ public Operation CreateOperation(){ return new OperationDiv(); } } //立钻哥哥:class DivFactory:IFactory{}
//C、创建一个Operation运算类 public class Operation{ private double _numberA = 0; private double _numberB = 0;
public double NumberA{ get{ return _numberA; } set{ _numberA = value; } }
public double NumberB{ get{ return _numberB; } set{ _numberB = value; } }
public virtual double GetResult(){ double result = 0; return result; } } //立钻哥哥:public class Operation{} // //加减乘除类(继承public class Operation{}) // //C.1、加法类,继承运算类 class OperationAdd : Operation{ public override double GetResult(){ double result = 0; resutl = NumberA + NumberB; return result; } } //立钻哥哥:class OperationAdd:Operation{} // //C.2、减法类,继承运算类 class OperationSub : Operation{ public override double GetResult(){ double result = 0; result = NumberA - NumberB; return result; } } //立钻哥哥:class OperationSub:Operation{} // //C.3、乘法类,继承运算类 class OperationMul : Operation{ public override double GetResult(){ double result = 0; result = NumberA * NumberB; return result; } } //立钻哥哥:class OperationMul:Operation{} // //C.4、除法类,继承运算类 class OperationDiv : Operation{ public override double GetResult(){ double result = 0; if(NumberB == 0){ throw new Exception(“立钻哥哥:除数不能为0。”); }
result = NumberA / NumberB; return result; } } //立钻哥哥:class OperationDiv:Operation{}
//D、客户端的代码 IFactory operFactory = new AddFactory(); Operation oper = operFactory.CreateOperation(); oper.NumberA = 11; oper.NumberB = 100; double result = oper.GetResult();
|
##2B.03、抽象工厂模式(Abstract Factory) |
++2B.03、抽象工厂模式(Abstract Factory)
++++立钻哥哥:【抽象工厂模式(Abstract Factory)】:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
++++抽象工厂模式是工厂方法模式的升级版本,在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象时一种非常好的解决方式。
++抽象工厂模式实现
++++AbstractProductA和AbstractProductB是两个抽象产品。
++++ProductA1、ProductA2和ProductB1、ProductB2就是两个抽象产品的具体分类的实现。
++++IFactory是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法。
++++ConcreteFactory1和ConcreteFactory2就是具体的工厂。
++++通常是在运行时刻再创建一个ConcreteFactory类的实例,这个具体的工厂再创建具有特定实现的产品对象。(也就是说:为创建不同的产品对象,客户端应使用不同的具体工厂。)
##2B.04、建造者模式(Builder) |
++2B.04、建造者模式(Builder)
++++立钻哥哥:【建造者模式(Builder)】:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
++++建造者模式(Builder Pattern)也叫做:生成器模式。
++++建造者模式的好处:使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。
++建造者模式基本代码:
++++【Builder】:是为创建一个Product对象的各个部件指定的抽象接口;
++++【ConcreteBuilder】:是具体建造者,实现Builder接口,构造和装配各个部件。
++++【Product】:就是产品角色。
++++【Director】:是指挥者,它是构建一个使用Builder接口的对象。(主要是用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化)
//立钻哥哥:建造者模型基本代码
//A、Product类:产品类,由多个部件组成 class Product{ List<string> parts = new List<string>();
//添加产品部件 public void Add(string part){ parts.Add(part); }
public void Show(){ Console.WriteLine(“立钻哥哥:产品 创建 ----”); foreach(string part in parts){ Console.WriteLine(part); } } } //立钻哥哥:class Product{}
//B、Builder类:抽象建造者类,确定产品由两个部件PartA和PartB组成,并声明一个得到产品建造后结果的方法GetResult: abstract class Builder{ public abstract void BuildPartA(); public abstract void BuildPartB(); public abstract Product GetResult(); } //立钻哥哥:abstract class Builder{} // //B.1、ConcreteBuilder1类:具体建造者类 class ConcreteBuilder1 : Builder{ private Product product = new Product();
public override void BuilderPartA(){ product.Add(“立钻哥哥:部件A”); }
public override void BuilderPartB(){ product.Add(“立钻哥哥:部件B”); }
public override Product GetResult(){ return product; } } //立钻哥哥:class ConcreteBuilder1:Builder{} // //B.2、ConcreteBuilder2类:具体建造者类 class ConcreteBuilder2 : Builder{ private Product product = new Product();
public override void BuildPartA(){ product.Add(“立钻哥哥:部件X”); }
public override void BuildPartB(){ product.Add(“立钻哥哥:部件Y”); }
public override Product GetResult(){ return product; } } //立钻哥哥:class ConcreteBuilder2:Builder{}
//C、Director类:指挥者类 class Director{ public void Construct(Builder builder){ builder.BuildPartA(); builder.BuildPartB(); } } //立钻哥哥:class Director{}
//D、客户端代码,客户不需知道具体的建造过程 static void Main(string[] args){ Director director = new Director(); Builder b1 = new ConcreteBuilder1(); Builder b2 = new ConcreteBuilder2();
//指挥者用ConcreteBuilder1的方法来建造产品 director.Construct(b1); Product p1 = b1.GetResult(); p1.Show();
//指挥者用ConcreteBuilder2的安防来建造产品 director.Construct(b2); Product p2 = b2.GetResult(); p2.Show();
Debug.Log(“立钻哥哥:建造者模式演示完毕~~”); }
|
##2B.05、原型模式(Prototype) |
++2B.05、原型模式(Prototype)
++++立钻哥哥:【原型模式(Prototype)】:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
++++原型模式的核心是一个clone方法,通过该方法进行对象的拷贝。
++++原型模式就是由一个正本可以创建多个副本的概念:一个对象的产生可以不由零起步,直接从一个已经具备一定雏形的对象克隆,然后再修改为生产需要的对象。
++原型模式代码
++++原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。
++++Prototype:声明一个克隆自身的接口;
++++ConcretePrototype:实现一个克隆自身的操作;
++++Client:让一个原型克隆自身从而创建一个新的对象;
//立钻哥哥:Prototype原型模式
//A、原型类 abstract class Prototype{ private string id; public string Id{ get{ return id; } }
public Prototype(string id){ this.id = id; }
//立钻哥哥:抽象类关键就是有这样一个Clone方法 public abstract Prototype Clone();
} //立钻哥哥:abstract class Prototype{}
//B、具体原型类 class ConcretePrototype1 : Prototype{ public ConcretePrototype1(string id) : base(id){ }
public override Prototype Clone(){ return (Prototype)this.MemeberwiseClone(); }
} //立钻哥哥:class ConcretePrototype1:Prototype{}
//C、客户端代码 static void Main(string[] args){ ConcretePrototype1 p1 = new ConcretePrototype1(“立钻哥哥”);
//克隆类ConcretePrototype1的对象p1就能得到新的实例c1 ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone(); }
//补充说明:对于.NET而言,原型抽象类Prototype是用不着的,因为克隆实在是太常用了,所以.NET在System命名空间中提供了ICloneable接口,其中就是唯一的一个方法Clone(),这样只需要实现这个接口就可以完成原型模式了。
|
##2B.06、适配器模式(Adapter) |
++2B.06、适配器模式(Adapter)
++++立钻哥哥:【适配器模式(Adapter)】:将一个类的接口转换成客户希望的另外一个接口。(Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。)
++++适配器模式是一个补偿模式,或者说是一个“补救”模式,通常用来解决接口不相容的问题,在百分之百的完美设计中是不可能使用到的。
++适配器模式代码实现
++++【Target】:目标角色。(该角色定义把其他类转换为何种接口,也就是我们的期望接口)
++++【Client】:与符合Target接口的对象协同;
++++【Adaptee】:源角色。(定义一个已经存在的接口,这个接口需要适配)
++++【Adapter】:适配器角色。(对Adaptee的接口与Target接口进行适配)
//立钻哥哥:Adapter适配器模式代码实现
//A、Target类(这是客户所期望的接口。目标可以是具体的或抽象的类,也可以是接口) class Target{ public virtual void Request(){ Debug.Log(“立钻哥哥:----普通请求----”); } } //立钻哥哥:class Target{}
//B、Adaptee类(需要适配的类) class Adaptee{ public void SpecificRequest(){ Debug.Log(“立钻哥哥:----特殊请求----”); } } //立钻哥哥:class Adaptee{}
//C、Adapter类(通过在内部包装一个Adaptee对象,把源接口转换成目标接口) class Adapter : Target{ //建立一个私有的Adaptee对象 private Adaptee adaptee = new Adaptee();
public override void Request(){ //这样就可把表面上调用Request()方法变成实际调用SpecificRequest() adaptee.SpecificRequest(); } } //立钻哥哥:class Adapter:Target{}
//D、客户端代码 static void Main(string[] args){ Target target = new Adapter(); target.Request(); //对客户端来说,调用的就是Target的Request()
Debug.Log(“立钻哥哥:----适配器模式演示完毕~~”); }
|
++适配器模式的优点
++++优点1:适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定他们就成。
++++优点2:增加了类的透明性。(我们访问的Target目标角色,但是具体的实现都委托给了源角色,而这些对高层次模块是透明的,也是它不需要关心的。)
++++优点3:提高了类的复用度。(源角色在原有的系统中还是可以正常使用,而在目标角色中也可以充当新的演员。)
++++优点4:灵活性非常好。(如果不想要适配器了,删除掉就可以了,其他的代码都不用修改,基本上就类似一个灵活的构件,想用就用,不想要就卸载。)
##2B.07、装饰模式(Decorator) |
++2B.07、装饰模式(Decorator)
++++立钻哥哥:【装饰模式(Decorator)】:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
++++装饰模式是对继承的有力补充。(继承是静态地给类增加功能,而装饰模式则是动态地增加功能。)
++装饰模式的代码实现
++++【Component】:是定义一个对象接口,可以给这些对象动态地添加职责。(在装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component抽象构件。)
++++【ConcreteComponent】:是定义了一个具体的对象,也可以给这个对象添加一些职责。(具体构件,是最核心、最原始、最基本的接口或抽象类的实现,我们要装饰的就是它。)
++++【Decorator】:装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator的存在的。(装饰角色,一般是一个抽象类,实现接口或者抽象方法,它里面可不一定有抽象的方法,在它的属性里必然有一个private变量指向Component抽象构件。)(维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。)
++++【ConcreteDecorator】:是具体的装饰对象,起到给Component添加职责的功能。(向组件添加职责。)
//立钻哥哥:Decorator装饰模式的代码实现
//A、Component类 abstract class Component{ public abstract void Operation(); } //立钻哥哥:abstract class Component{}
//B、ConcreteComponent类 class ConcreteComponent : Component{ public override void Operation(){ Debug.Log(“立钻哥哥:----具体对象的操作----”); } } //立钻哥哥:class ConcreteComponent:Component{}
//C、Decorator类 abstract class Decorator : Component{ protected Component component;
//设置Component public void SetComponent(Component component){ this.component = component; }
//重写Operation(),实际执行的是Component的Operation() public override void Operation(){ if(component != null){ component.Operation(); } } } //立钻哥哥:abstract class Decorator:Component{}
//D.1、ConcreteDecoratorA类 class ConcreteDecoratorA : Decorator{ //本类的独有功能,以区别于ConcreteDecoratorB private string addedState;
public override void Operation(){ //首先运行原Component的Operation(),再执行本类的功能,如addedState,相当于对原Component进行了装饰。 base.Operation(); addedState = “立钻哥哥”;
Debug.Log(“立钻哥哥:具体装饰对象A的操作”); }
} //立钻哥哥:class ConcreteDecoratorA:Decorator{}
//D.2、ConcreteDecoratorB类 class ConcreteDecoratorB : Decorator{ public override void Operation(){ //首先运行原Component的Operation(),再执行本类的功能,如AddedBehaviour(),相当于对原Component进行了装饰 base.Operation(); AddedBehaviour();
Debug.Log(“立钻哥哥:----具体装饰对象B的操作”); }
//本类独有的方法,以区别于ConcreteDecoratorA private void AddedBehaviour();
} //立钻哥哥:class ConcreteDecoratorB:Decorator{}
//E、客户端代码 static void Main(string[] args){ ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB();
//装饰的方法是:首先用ConcreteComponent实例化对象c,然后用ConcreteDecoratorA的实例化对象d1来包装c,再用ConcreteDecoratorB的对象d2包装d1,最终执行d2的Operation(); d1.SetComponent(c); d2.SetComponent(d1); d2.Operation();
Debug.Log(“立钻哥哥:----装饰模式演示完毕~~”); } //立钻哥哥:static void Main(string[] args){}
|
##2B.08、桥接模式(Bridge) |
++2B.08、桥接模式(Bridge)
++++立钻哥哥:【桥接模式(Bridge)】:将抽象部分与它的实现部分分离,使它们都可以独立地变化。
++++桥接模式的意图是对变化的封装,尽量把可能变化的因素封装到最细、最小的逻辑单元中,避免风险扩散。(在进行系统设计时,发现类的继承有N层时,可以考虑使用桥接模式。)
++++Bridge桥接模式:在系统开始时就被使用,它使得抽象接口和实现部分可以独立进行改变;
++桥接模式的代码实现
++++【Abstraction】:抽象化角色。(它的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色一般是抽象类。)(维护一个指向Implementor类型对象的指针)
++++【Implementor】:实现化角色。(它是接口或者抽象类,定义角色必须的行为和属性。)(一般来讲,Implementor接口仅提供基本操作,而Abstraction则定义了基于这些基本操作的较高层次的操作。)
++++【RefinedAbstraction】:修正抽象化角色。(它引用实现化角色对抽象化角色进行修正。)(扩充由Abstraction定义的接口。)
++++【ConcreteImplementor】:具体实现化角色。(它实现接口或抽象类定义的方法和属性。)
++++协作:Abstraction将Client的请求转发给它的Implementor对象;
//立钻哥哥:Bridge桥接模式的代码实现
//A、Implementor类 abstract class Implementor{ public abstract void Operation(); } //立钻哥哥:abstract class Implementor{}
//B.1、ConcreteImplementorA派生类 class ConcreteImplementorA : Implementor{ public override void Operation(){ Debug.Log(“立钻哥哥:----具体实现A的方法执行----”); } } //立钻哥哥:class ConcreteImplementorA:Implementor{} // //B.2、ConcreteImplementorB派生类 class ConcreteImplementorB : Implementor{ public override void Operation(){ Debug.Log(“立钻哥哥:----具体实现B的方法执行----”); } } //立钻哥哥:class ConcreteImplementorB:Implementor{}
//C、Abstraction类 class Abstraction{ protected Implementor implementor;
public void SetImplementor(Implementor implementor){ this.implementor = implementor; }
public virtual void Operation(){ implementor.Operation(); }
} //立钻哥哥:class Abstraction{}
//D、RefinedAbstraction类 class RefinedAbstraction : Abstraction{ public override void Operation(){ implementor.Operation(); } } //立钻哥哥:class RefinedAbstraction:Abstraction{}
//E、客户端实现 static void Main(stirng[] args){ Abstraction ab = new RefinedAbstraction();
ab.SetImplementor(new ConcreteImplementorA()); ab.Operation();
ab.SetImplementor(new ConcreteImplementorB()); ab.Operation();
Debug.Log(“立钻哥哥:----桥接模式演示完毕~~”); }
|
##2B.09、组合模式(Composite) |
++2B.09、组合模式(Composite)
++++立钻哥哥:【组合模式(Composite)】:将对象组合成树形结构以表示“部分-整体”的层次结构。(组合模式使得用户对单个对象和组合对象的使用具有一致性。)
++++组合模式定义了包含基本对象和组合对象的类层次结构。
++Composite组合模式代码实现
++++【Component】:抽象构件角色。(定义参与组合对象的共有方法和属性,可以定义一些默认的行为或属性。)(声明一个接口用于访问和管理Component的子组件)
++++【Leaf】:叶子构件。(叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。)
++++【Composite】:树枝构件。(树枝对象,它的作用是组合树枝节点和叶子节点形成一个树形结构。)
++++【Client】:通过Component接口操纵组合部件的对象;
++++协作:用户使用Component类接口与组合结构中的对象进行交互。(如果接受者是一个叶节点,则直接处理请求。如果接受者是Composite,它通常将请求发送给它的子部件,在转发请求之前与/或之后可能执行一些辅助操作。)
//立钻哥哥:Composite组合模式代码实现
//A、Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component的子部件 abstract class Component{ protected string name;
public Component(string name){ this.name = name; }
//通常都用Add和Remove方法来提供增加或移除树叶或树枝的功能 public abstract void Add(Component c); public abstract void Remove(Component c); public abstract void Display(int depth); } //立钻哥哥:abstract class Component{}
//B、Leaf组合中表示叶节点对象,叶节点没有子节点 class Leaf : Component{ public Leaf(string name) : base(name){ }
//由于叶子没有再增加分枝和树叶,所以Add和Remove方法实现它没有意义,但这样做可以消除叶节点和枝节点对象在抽象层次的区别,它们具有完全一致的接口
public override void Add(Component c){ Debug.Log(“立钻哥哥:----Cannot add to a leaf.---”); }
public override void Remove(Component c){ Debug.Log(“立钻哥哥:----Cannot remove from a leaf.---”); }
//叶节点的具体方法,此处是显示其名称和级别 public override void Display(int depth){ Debug.Log(new string(‘-’, depth) + name); }
} //立钻哥哥:class Leaf:Component{}
//C、Composite定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加Add和删除Remove class Composite : Component{ //一个子对象集合用来存储其下属的枝节点和叶节点 private List<Component> children = new List<Component>();
public Composite(string name) : base(name){ }
public override void Add(Component c){ children.Add(c); }
public override void Remove(Component c){ children.Remove(c); }
public override void Display(int depth){ Debug.Log(new string(‘-’, depth) + name);
foreach(Component component in children){ component.Display(depth + 2); } }
} //立钻哥哥:class Composite:Component{}
//D、客户端代码,能通过Component接口组合部件的对象 static void Main(string[] args){ //生成树根root,根上长出两叶LeafA和LeafB Composite root = new Composite(“root”); root.Add(new Leaf(“Leaf A”)); root.Add(new Leaf(“Leaf B”));
//根上长出分枝CompositeX,分枝上也有两叶LeafXA和LeafXB Composite comp = new Composite(“Composite X”); comp.Add(new Leaf(“Leaf XA”)); comp.Add(new Leaf(“Leaf XB”)); root.Add(comp);
//在CompositeX上再长出分枝CompositeXY,分枝上也有两叶LeafXYA和LeafXYB Composite comp2 = new Composite(“Composite XY”); comp2.Add(new Leaf(“Leaf XYA”)); comp2.Add(new Leaf(“Leaf XYB”)); comp.Add(comp2);
//根部又长出两叶LeafC和LeafD,可惜LeafD每长牢,被风吹走了 root.Add(new Leaf(“Leaf C”));
Leaf leaf = new Leaf(“Leaf D”); root.Add(leaf); root.Remove(leaf);
//显示大树的样子 root.Display(1);
Debug.Log(“立钻哥哥:----组合模式演示完毕~~”); }
//E、结果显示
|
##2B.10、享元模式(Flyweight) |
++立钻哥哥推荐的拓展学习链接(Link_Url):
++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/
++++Unity面试题ABC:https://blog.csdn.net/vrunsoftyanlz/article/details/78630687
++++Unity面试题DEF:https://blog.csdn.net/VRunSoftYanlz/article/details/78630838
++++设计模式简单整理:https://blog.csdn.net/vrunsoftyanlz/article/details/79839641
++++专题:设计模式(精华篇):https://blog.csdn.net/VRunSoftYanlz/article/details/81322678
++++Lua快速入门篇(Xlua拓展):https://blog.csdn.net/VRunSoftYanlz/article/details/81173818
++++Lua快速入门篇(XLua教程):https://blog.csdn.net/VRunSoftYanlz/article/details/81141502
++++Lua快速入门篇(基础概述):https://blog.csdn.net/VRunSoftYanlz/article/details/81041359
++++框架知识点:https://blog.csdn.net/VRunSoftYanlz/article/details/80862879
++++游戏框架(UI框架夯实篇):https://blog.csdn.net/vrunsoftyanlz/article/details/80781140
++++游戏框架(初探篇):https://blog.csdn.net/VRunSoftYanlz/article/details/80630325
++++U3D小项目参考:https://blog.csdn.net/vrunsoftyanlz/article/details/80141811
++++UML类图:https://blog.csdn.net/vrunsoftyanlz/article/details/80289461
++++Unity知识点0001:https://blog.csdn.net/vrunsoftyanlz/article/details/80302012
++++Unity知识点0008:https://blog.csdn.net/VRunSoftYanlz/article/details/81153606
++++U3D_Shader编程(第一篇:快速入门篇):https://blog.csdn.net/vrunsoftyanlz/article/details/80372071
++++U3D_Shader编程(第二篇:基础夯实篇):https://blog.csdn.net/vrunsoftyanlz/article/details/80372628
++++Unity引擎基础:https://blog.csdn.net/vrunsoftyanlz/article/details/78881685
++++Unity面向组件开发:https://blog.csdn.net/vrunsoftyanlz/article/details/78881752
++++Unity物理系统:https://blog.csdn.net/vrunsoftyanlz/article/details/78881879
++++Unity2D平台开发:https://blog.csdn.net/vrunsoftyanlz/article/details/78882034
++++UGUI基础:https://blog.csdn.net/vrunsoftyanlz/article/details/78884693
++++UGUI进阶:https://blog.csdn.net/vrunsoftyanlz/article/details/78884882
++++UGUI综合:https://blog.csdn.net/vrunsoftyanlz/article/details/78885013
++++Unity动画系统基础:https://blog.csdn.net/vrunsoftyanlz/article/details/78886068
++++Unity动画系统进阶:https://blog.csdn.net/vrunsoftyanlz/article/details/78886198
++++Navigation导航系统:https://blog.csdn.net/vrunsoftyanlz/article/details/78886281
++++Unity特效渲染:https://blog.csdn.net/vrunsoftyanlz/article/details/78886403
++++Unity数据存储:https://blog.csdn.net/vrunsoftyanlz/article/details/79251273
++++Unity中Sqlite数据库:https://blog.csdn.net/vrunsoftyanlz/article/details/79254162
++++WWW类和协程:https://blog.csdn.net/vrunsoftyanlz/article/details/79254559
++++Unity网络:https://blog.csdn.net/vrunsoftyanlz/article/details/79254902
++++C#事件:https://blog.csdn.net/vrunsoftyanlz/article/details/78631267
++++C#委托:https://blog.csdn.net/vrunsoftyanlz/article/details/78631183
++++C#集合:https://blog.csdn.net/vrunsoftyanlz/article/details/78631175
++++C#泛型:https://blog.csdn.net/vrunsoftyanlz/article/details/78631141
++++C#接口:https://blog.csdn.net/vrunsoftyanlz/article/details/78631122
++++C#静态类:https://blog.csdn.net/vrunsoftyanlz/article/details/78630979
++++C#中System.String类:https://blog.csdn.net/vrunsoftyanlz/article/details/78630945
++++C#数据类型:https://blog.csdn.net/vrunsoftyanlz/article/details/78630913
++++Unity3D默认的快捷键:https://blog.csdn.net/vrunsoftyanlz/article/details/78630838
++++游戏相关缩写:https://blog.csdn.net/vrunsoftyanlz/article/details/78630687
++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/
--_--VRunSoft : lovezuanzuan--_--