设计模式?到底什么是设计模式?仍是直接去抄一下定义吧。设计模式是针对上下文的特定问题的解决方案。也就是一种解决问题的思路。编程
在说设计模式以前,咱们仍是要提一下七大原则:开闭原则、依赖倒转原则、单一职责原则、里氏替换原则、复合复用原则、迪米特原则、接口隔离原则。这几个原则就是简单的说一下,并非须要花太多的时间去说,由于说多了也记不出。设计模式
1、状态模式mvc
当一个对象的内在状态改变时容许改变其行为,这个对象看起来像是改变了其类。其实吧,当我使用这个状态模式的时候,感受这个状态模式能够理解成为具体对象抽象化,就是咱们所说的子类父类的关系,父类中的方法都是通常化,子类具体实现就好了。使用这个模式的时候咱们须要定义一个入口对象(上下文环境)Context ,在这个对象中具体去实现你要实现的对象就好了。其实这样作的好处就是咱们不用大量的去对相同结构的对象去写一些相同的字段或者方法了,下面是网上的图片:学习
这个state抽象类你能够不用写成抽象,也能够写成通常类或者接口,由于状态模式的本质就是子类通常化。在这中模式中咱们通常会使用一个controller来管理状态,不一样的state在这个controller中进行切换。this
2、外观模式spa
外观模式是一种使用频率很是好的结构型设计模式,它经过引入一个外观角色来简化客户端与子系统之间的交互,为复杂的子系统调用提供了一个统一的入口,下降子系统与客户端之间的耦合度,且客户端调用很是方便。设计
说到这里,其实咱们并不难的理解外观模式是用来减小耦合度的。咱们也能够这样去理解,在软考中的1:m,这样就能够很容易去知道了1是指的客户端,也就是外界访问,那就是多个子系统。这里要特别说明的一下的是,子系统之间是不能够相互调用,若是调用的话就变成了中介者模式了。外界与内部调用是经过一个中间变量来执行的。下面是图:日志
3、单例模式(跳过)code
4、中介者模式对象
首先第一句中介者模式的关系是m:n。为了是思路更加明白,中介者模式只是对子系统之间而言的,并不对外界有影响。每一个子系统若是想要去调用别的子系统的话,咱们通常的作法不会让他们直接去调用的,而是去找个中间变量去来管理他们,这个中间变量就是中介者。说到这里咱们其实已经很明白外观模式与中介者的区别了,可是咱们在实际开发中,咱们仍是会把他们放在一块儿使用的,由于分外写没有必要。他们本质就是管理,使代码之间的耦合下降,功能单一。这个是很是符合软件开发的单一指责原则的。图:
5、桥接模式
关于这个模式,咱们仍是先来看看这个模式的意图吧。将抽象部分与它的实现部分分离,使他们能够独立的变化。在学习这个部分的时候,咱们不能把它单独的来讲,必定要与前面进行比较来学。状态模式是将具体类抽象成一个类,客户端与这个抽象类进行打交道,这个特色是一个实体,一个是抽象。咱们如今作的一件事情就是,当咱们的客户变成多个具备相同特色,又有一些不一样的时候的,那咱们有应该这么去作呢?最好的办法就是将客户端也进行抽象,那么就变成了两个抽象类进行交互了,这样的链接模式就是桥接模式。在这里的时候咱们发现,就是在这前面的模式,他们都是为了减小耦合的,为了这个,就须要提取公共的特色,这个提取的过程就是抽象类。或者能够这样的去认为,桥接模式就是两个状态模式。图:
6、工厂模式
在面向对象编程中,最一般的方法是一个new操做符产生一个对象实例,new操做符就是用来构造对象实例的。可是在一些状况下,new操做符直接生成对象会带来一些问题。举个例子说,许多类型对象的建立须要一系列的步骤:你可能须要计算或取得对象的初始设置;选择生成哪一个子对象实例;或在生成你须要的对象以前必须先生成一个辅助功能的对象。在这些状况新对象的创建就是一个“过程”。不只是一个操做,像一个大机器中的一个齿轮传动。
工厂模式分为简单工厂模式、工厂方法模式、抽象工厂模式。咱们一个一个说明。
简单工厂模式
代码以下:
#region 产品类 //基类 通常的做用就是将子类的共有的方法聚集过来 //避免重复写 public abstract class BWM { public BWM() { } } public class BWM320 : BWM { public BWM320() { Console.WriteLine("制造-->BWM320"); } } public class BWM523 : BWM { public BWM523() { Console.WriteLine("制造-->BWM523"); } } #endregion #region 工厂类 public class Factory { public BWM CreateBWM(int type) { switch (type) { case 320: return new BWM320(); case 523: return new BWM523(); default: break; } return null; } } #endregion #region 客户类 class Program { static void Main(string[] args) { Factory factory = new Factory();//实例化简单工厂 BWM bWM320 = factory.CreateBWM(320); BWM bwm523 = factory.CreateBWM(523); Console.ReadKey(); } } #endregion
咱们从上面的代码上能够看出,先将产品的基类写出来,而后再生成子类,这个部分就是产品类;接着咱们的作法就是直接建立一个工厂类,这个工厂类是一个普通的类,在这个里面咱们写一个方法,在外面能够经过这个方法传参,就能够在factory类中建立你须要指定的产品类了,可是这个方法有一个缺点,若是咱们这个时候再来一个产品类的话,咱们就是在factory再进行修改。这样作的方式是很差的,由于咱们在设计软件软件中有一个原则 就是对拓展开放,对修改封闭。就是咱们在进行建立的时候,咱们应该知道若是多个类他们的方法是同样的,可是须要不一样的数据的话,咱们就应该为他们建立一个基类,因此这个factory也是应该建立一个基类的,全部下面就是第二个了。
工厂方法模式
#region 产品类 public abstract class BMW { public BMW() { } } public class BMW320 : BMW { public BMW320() { Console.WriteLine("制造-->BMW320"); } } public class BMW523 : BMW { public BMW523() { Console.WriteLine("制造-->BMW523"); } } #endregion #region 建立工厂类 interface FactoryBMW { BMW CreateBMW(); } public class FactoryBMW320 : FactoryBMW { public BMW CreateBMW() { return new BMW320(); } } public class FactoryBMW523 : FactoryBMW { public BMW CreateBMW() { return new BMW523(); } } #endregion class Program { static void Main(string[] args) { FactoryBMW320 factoryBMW320 = new FactoryBMW320(); BMW320 bMW320 = (BMW320)factoryBMW320.CreateBMW(); FactoryBMW523 factoryBMW523 = new FactoryBMW523(); BMW523 bMW523 = (BMW523)factoryBMW523.CreateBMW(); Console.ReadKey(); } }
其实咱们不难发现就是将工厂进行抽象化,就是所说的那个提取基类,咱们在使用的时候只须要用指定的基类。若是你是须要使用BMW320的话,你只要去实例化BMW320的工厂类就好了,可是这样的话仍是出现一个问题,若是咱们又有新的功能的话,又怎么办了?其实在这种功能常常进行变动的地方,咱们必定要注意抽象方法提取基类的思想。
下面就是抽象工厂方法
#region 产品类 //发动机以及型号 public interface Engine { } public class EngineA : Engine { public EngineA() { Console.WriteLine("制造-->EngineA"); } } public class EngineB : Engine { public EngineB() { Console.WriteLine("制造-->EngineB"); } } //空调以及型号 public interface Aircondition { } public class AirconditionA : Aircondition { public AirconditionA() { Console.WriteLine("制造-->AirconditionA"); } } public class AirconditionB : Aircondition { public AirconditionB() { Console.WriteLine("制造-->AirconditionB"); } } #endregion #region 建立工厂类 //建立工厂的接口 public interface AbstractFactory { //制造发动机 Engine CreateEngine(); //制造空调 Aircondition CreteAirconition(); } //为宝马320系列生产配件 public class FactoryBMW320 : AbstractFactory { public Engine CreateEngine() { return new EngineA(); } public Aircondition CreteAirconition() { return new AirconditionA(); } } //为宝马523系列生产配件 public class FactoryBMW523 : AbstractFactory { public Engine CreateEngine() { return new EngineB(); } public Aircondition CreteAirconition() { return new AirconditionB(); } } #endregion class Program { static void Main(string[] args) { //生产宝马320系列配件 FactoryBMW320 factoryBMW320 = new FactoryBMW320(); factoryBMW320.CreateEngine(); factoryBMW320.CreteAirconition(); //生产宝马523系列配件你 FactoryBMW523 factoryBMW523 = new FactoryBMW523(); factoryBMW523.CreateEngine(); factoryBMW523.CreteAirconition(); Console.ReadKey(); } }
其实这样的作法就是咱们给工厂的子类提供一个接口,若是咱们添加需求的时候,咱们就能够在工厂子类里进行显示。仍是那句话,提取基类。
不管是简单工厂模式,工厂方法模式,仍是抽象工厂模式,他们都属于工厂模式,在形式和特色上也是极为类似的,他们的最终目的都是解耦。在使用时,咱们没必要去在乎这个模式究竟是工厂模式仍是抽象工厂模式,由于他们之间的演变经常是使人捉摸不透的。常常你会发现,明明使用的工厂模式,当新需求来临时,稍加修改,加入了一个新的方法后,因为类中的产品构成了不一样等级结构中的产品族,它就变成抽象工厂模式,当减小一个方法时的提供的产品再也不构成产品族以后,它就演变了工厂方法模式。
七建造者模式
建造者模式使用多个简单的对象一步一步构造一个复杂的对象。这种类型的设计模式属于建立者模式,它提供了一种建立对象的对象方式。在编程中,咱们仍是要知道一点的,就是当你去建立一个对象的时候,若是这个对象的功能实在是太多了。好比说,这个对象须要建立身体,须要建立武器,须要建立特效等等,当咱们把它的具体实现类所有放在一个类中去完成,这显然是很差的,由于这个违背了对修改关闭,对拓展开放的原则。管理者其实要作的就是咱们只要知道流程就好了,具体的可让各个部分去作,其实建造者模式就是这个原理。建造者会把一个功能庞大的对象进行分解,每个部分只须要去完成一个小的部分,而后管理者再进行组装,若是有的地方要使用对象的话,就直接向这个管理者提要求,让管理者去作就好了。
十一命令模式
将一个请求封装成一个对象(即咱们建立的command对象)从而使你可用不一样的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操做。子软件系统中,行为请求者与行为实现者一般是一种紧耦合的关系,但在某些场合,好比须要对行为进行记录、撤销或者重作、事务等处理时,这种没法抵御变化的紧耦合的设计模式就不太合适了。咱们在设计软件的时候,若是让接受与发送者两个职能放在一块儿的话,就会出现耦合性比较高的状况,咱们要作的就是将职能进行分开,让发送与接受分红单独的类
/// <summary> /// 接收者类,知道如何实施与执行一个请求相关的操做,任何类均可能做为一个接收者 /// </summary> public class Receiver { /// <summary> /// 真正的命令实现 /// </summary> public void Action() { Console.WriteLine("Excete request"); } } /// <summary> /// 抽象命令类,用来声明执行操做的接口 /// </summary> public interface ICommand { void Excete(); } /// <summary> /// 具体命令类,实现具体命令 /// </summary> public class ConcerteCommand : ICommand { private Receiver receiver; //具体命令类包含有一个接收者,将这个接收者对象绑定与一个动做 public ConcerteCommand(Receiver receiver) { this.receiver = receiver; } /// <summary> /// 说这个实现是虚的,由于他是经过调用接收者相对应的操做来实现Excete的 /// </summary> public void Excete() { receiver.Action(); } } /// <summary> /// 调度类,要求该命令执行这个请求 /// </summary> public class Invoker { private ICommand command; /// <summary> /// 设置命令 /// </summary> /// <param name="command"></param> public void SetCommand(ICommand command) { this.command = command; } /// <summary> /// 执行命令 /// </summary> public void ExceteCommand() { command.Excete(); } } class Program { static void Main(string[] args) { Receiver receiver = new Receiver(); ICommand command = new ConcerteCommand(receiver); Invoker invoker = new Invoker(); invoker.SetCommand(command); invoker.ExceteCommand(); Console.ReadKey(); } }
咱们从代码中能够看出,咱们先要初始化一个receiver(接收者类),这个类是你不须要知道你去让外界去工做,只须要外界发出命令请求的时候,这个类只须要去作就好了,这个是一个单向的,就比较像mvc模式中的view类同样,只须要去作就好了。另外再说一句就是这个receiver类是一个具体执行的类。