设计模式思考

面向对象和设计模式的一些思考总结(极致浓缩版)

  1. 高层模块不应该依赖于底层模块,应该在他们之间建立一个抽象层,来实现可替换的底层,不变的接口层。这个是面向对象的更高境界了,面向接口编程。上层和下层通过唯一途径联系就是接口,
  2. 这有点类似与操作系统和软件和硬件之间的关系,他们的联系也是通过能够接触到那一层接口来实现。可以说我们只需知道接口就能完成调用其他模块的功能而不需要知道实现的具体细节,这也正是面向对象的精髓所在。面向接口编程,不同模块的替换就能像拔掉插销,像电脑更换零件一样简单,而不会对一个系统造成大的影响。这就是所谓的高内聚,低耦合吧。内聚在同一模块里面,低耦合在只通过特定接口联系。

类生成和创建的设计模式:

  1. 简单工厂模式

    • 用于类生成,用统一工厂配合不同参数生成不同的类,里面的类可以增加拓展。并且可以通过factory类进行类项目的设定,设定完成后然后再进行生成。并且工厂类返回的可以是父类,利用多态性质,实现动态绑定。生成多种不同子类时候可以简单使用。
    • 思考:这里简单工厂最大的作用就是让对象生成变得和谐,而不用考虑很多怎样生成特定对象需要传递什么参数问题,只要简单的传递你想要生成的对象的名称工厂就能帮你生成正确的对象。统一接口。生成不同对象之时,工厂其实还可以增加生成类,这时候直接调用就更方便了,甚至不用传递特定参数。
  2. 策略模式

    • 就是利用多态性进行父类操控子类,实现简单接口实现不同算法,这里的算法可以动态变换,到这里使用的是多态的性质。
    • 做法:用一个类进行包装,包装类调用相同的方法就可以实现不同算法的不同效果,为什么要这样做?因为包装类的相同接口更好记忆。如何把不同子类传递到包装的背景类里面,这里使用参数传递,通过父类接口,就可以方便的把同一个父类继承下来的子类通过多态传递到参数里面,然后直接调用父类方法就可以动态绑定了。这里一连串的目的还是为了让代码不需经常改动,从而达到更好维护的效果。相比简单工厂模式如果要增加子类就要改动工厂类方法,策略模式动态使用不同子类的方不用 频繁改动代码,只需把特定子类传递进去,然后调用同一个包装类的方法就可以了。
    • 思考: 其实想来想去,这样主要目的就是利用多态生成同一个算法父类调用方法,然后不同子类间的实现算法的效果不同,这里我直接通过父类操纵子类不就好了,包装类显得更加繁重。何必要多包了一层
    • 所以继续思考可以发现,为了让用户少知道不必要的子类是什么,例如子类一多要知道要调用什么子类也是很头疼。这里就可以和简单工厂模式结合,通过把背景类和简单工厂类结合,我只需要把适当的要生成的子类字符信息传入背景类,然后背景类自动生成子类,然后调用背景类的方法就能生成正确的结果。这里可以看到通过背景类和简单工厂的结合,用户只需要知道我这个背景类怎么使用就可以。相比简单工厂类还要知道父类和工厂生成类来说,这个耦合度更低。
  3. 建造者模式

    • 通过builder对象来设置繁杂的选项,然后通过build()方式产生对象。
    • 思考:简单来说就是通过builder这个中间层进行一些参数上的设置,比如说设置对象的一些参数。这时候为什么不直接通过对象本身来设置呢,大概是通过builder更加保密更加一致吧,有些对象的状态设置比较复杂,这时候调用builder的设置状态可以更为简单的调用builder的接口。说到底还是中间套一层,使得对象生成或设置更加简单。
  4. 装饰模式

    • 这个设计模式是为了动态为旧的类加入新功能的,如果直接修改旧的类,会让类变得更加复杂,不好维护。如果生成子类也不是非常方便,而装饰模式就是为了用户在满足特定条件下的生成的特定类,只是特定情况下使用,让这个新类包含原来的旧类,并且加上新功能,当用户需要新的特殊功能时候就可以使用这个新生成的类。有效的把核心职责和装饰指责分别开来了。
    • 思考:这个的实现,把原有的类作为成员放在新的装饰类里面,通过调用装饰类里面的方法就可以满足特定条件下的不同装饰功能。而且装饰类可以独立开来,把原有类当作参数传进装饰类的构造方法里面就能实现新的装饰功能。这个符合开放-封闭原则,不去改动原有类的核心代码,而去拓展新的功能来符合特定条件下的边缘功能。
  5. 代理模式

    • 为其他对象提供一种代理来控制对这个对象的访问。其实就是中间人,不是直接调用被访问的对象,而是通过代理对象来实现中间沟通。是在需要调用的类前再套上一个类,用于将该类进行某些限制行为。
    • *思考:用户程序员通过代理类来调用真正类的方法,这时候代理类作为第三方中间人,可以做的事有在代理类里面实现某些逻辑正确调用真正类的方法。对用户提供一个简单的接口,对用户权限进行一些控制。
      这个本质就是对用户和调用类之间又包了一层,用户只能通过代理类来操控真正类,从而能达到某些限制作用。*
  6. 工厂模式

    • 这里和前面的简单工厂模式不同,前面的简单工厂生成模式,在一开始需要判断分支,然后生成具体的类。如果有新的子类就需要更改简单工厂的代码,这里违背了开放闭合原则,频繁改动工厂的代码并不好。能增加而不改动原有代码是最理想情况。这时候工厂模式就是把工厂生成的方法声明为接口,在特定子类下实现接口,然后每多一个子类就多生成一个工厂类,这样的话就能实现灵活的工厂。不过就是代码量稍多,每次生成一个新的类型的类就要写一个新的类和一个新的工厂类。
    • 思考:坑爹,每生成一个新类,你还不是要通过客户端代码来实现新的一个工厂类然后生成新类,这时候我还得去知道哪个工厂类有哪些,生成了什么类,这不更麻烦吗。不过这个因为不用改动简单工厂里面的逻辑判断生成代码所以不违反开放-封闭原则。因为有可能简单工厂生成的子类多了以后,里面的逻辑变得越来越多,也不好管理。而工厂模式每生成一个类,也生成一个工厂,就不会改动其他代码。在我看来简单工厂模式里面只要不是生成太多的子类,我宁愿用简单工厂模式还简单点。具体工厂类还得继承工厂类,子类还的继承父类,然后都是通过父类接口调用,每生成一个类就要增加两个类,所以工厂类麻烦。

行为模式

  1. 观察者模型

    • 顾名思义,就是说有一个被观察者,许多观察者,被观察的人一动作,观察者都要做出响应。以前比较笨的方法就去轮询,观察者时时刻刻轮询被观察者的状态,这样低效率。这时候观察者模型就是说,被观察者动作了,它还主动提醒每个观察者说我动作了,你们该做出反应了。而且观察者不需要知道其他观察者的存在,只要知道被观察者就可以了。
    • 思考:这个模型是我认为运用的很多的一个模型 。这个被观察者维护着观察者的状态,保存着所有的观察者的接口句柄。然后通知的时候,利用观察者注册实现的接口进行回调即可。然后观察者可以自由注册监听被观察者,然后被观察者能动态增加或删除观察者,当观察者销毁时,被观察者应该及时删除该观察者的接口句柄,其实观察者也可以通过调用通知者方法来实现注销自身观察。这个模型在很多地方有用,例如你要维护多个界面的同一性,当数据状态改变的时候,界面能自动更新,这个时候就可以用观察者模型,还有mvc架构中,model数据层发生变化后,可以通过观察者模型自动通知view改变,也可以通过通知control,让control通知view改变,这样一来耦合度更低。

    • 观察者模型延伸委托模式:这个就是说前面观察者模型情况下,需要观察者实现相同的接口,这时候委托就是能将函数注册给通知者,当通知者要通知的时候,这些观察者的函数委托给通知者后,通知者能帮他们自觉调用这些观察者的方法,而无须注册监听通知者。但这些委托的方法必须有相同的参数列表和返回类型,即为相同的函数原型。

    • 思考:其实这些不就是监听者模型的延伸吗,你说观察者必须实现相同的接口,然后不能在接口里面调用自己不同的函数方法吗,这样还不是能够达到同样的不同方式的执行不同方法的目的。这个委托最多算是不用通知者维护响应的观察者状态了,直接让通知者调用所有的委托给委托对象的方法。总之委托就是使用起来方便一点的观察者模型,也能用观察者模型实现。当然这是前提是你能触碰到这些观察者并且能让他们注册通知者时候才行,如果不能接触到观察者类,只能通过委托方法的方式来实现监听回调,但仔细想想,你委托给委托对象时候,需要指定你委托给委托对象处理的是那个函数方法。这在不能触碰到类源码,只能通过类提供方法时候那时候用委托才可以实现观察者模型。这样想想,委托还确实蛮方便的,不用维护观察者和通知者之间的监听列表关系也是一大优点。能不能用委托也跟特定语言有关,像c#内部带有委托,而java就需要自己来实现这个方式。

通用思想

  1. 单一职责原则

    • 也就是同一个类一定要完成一类事情,别把不同功能的类都挤在一起了,太大的类不好维护,尽量拆解。然后通过组合的方式来管理。
    • 思考: 一个类不承担太多职责,这样调试起来也更加方便,组合才是这个世界的真谛。从小到大,现实世界也是这样,从原子到器官到人,都是组合起来的。所以说面向对象模拟现实也好,一个类不应该包揽很多不同属性的事情,不好维护。
  2. 开放封闭原则

    • 意思是对于拓展是开放的,对于修改是封闭的。这个意思是对于变化的需求,如果你需要改变你已经实现的东西来符合需求,这就是不好的,因为你试图去修改已有的代码,这样错的可能性也在增大。
    • 思考:说是这么说,要做到写好的类就不修改了,你能想好完全的事情哪有那么容易,所以要实现这个目标完全靠的是抽象,增加父类接口,要拓展时候,增加子类实现,然后动态绑定。这个说起来简单做起来却很困难,你要如何实现完好的抽象,而且项目如果过多的进行接口抽象,往往也会有理不清的逻辑。这些都要提前想清楚,对一个类修改很多总是不好的,修改意味着可能出错,而拓展就是新生成类来实现需求。而且当项目进行得越深,你想改变其中一些行为会变得越发困难。当初如果没有考虑好可能有的变动需求,改起来可能会很麻烦。
  3. 外观模式
    • 既是通过给用户最少知道的原则,把一些纷繁复杂的接口简单化,在包装后给用户使用。就不会显得那么多的接口,统一接口。
    • *思考:这个就是说把一些写好的类通过外观模式包装一下,使得它没那么纷繁复杂,方法数量没那么多。这也时常用于老系统重构,以前的系统代码太复杂了,就用外观模式再套一层,一部分人直接使用新的外观模式的接口,另一部分的人还需要和老的系统代码和新的外观模式接口直接进行转换。这就是计算机界俗称的有什么比较难解决的问题,不妨考虑在套一层中间转换一下。仔细想想这个和那个代理模式也没啥区别啊,和策略模式,工厂模式,简单工厂模式都是,通过用户和真正使用的对象之间再套一层,从而达到一些使用更简单,降低耦合度,控制权限等目的。都是中间套一层,看起来混乱时,来吧套一层。这就是为什么软件系统越做越大时候,你不知道它中间已经被套了多少层了。
      编写类时候要注意的事情:这个就是说你能让用户看到的都是用户能够使用到的有用的才把方法声明为public,否则声明为privite就好。因为太多方法用户看起来也累,也会不知道选哪个才好。然后又要去查看文档费时费力。 这个在自己实践的时候也挺常见的,很多时候有些方法的实现依赖于其他函数调用,这个时候,如果这些函数调用跟用户想使用的方法没有关系就把他们声名为private,这样用户就不会看到很多根本不是给他们使用或调用的方法。这里就是说很多时候你写的类方法别下意识就声名为public,有给用户用的才声明为public。*

你可能感兴趣的:(设计模式)