【关于设计模式】
设计模式的诞生
起源
与很多软件工程技术一样,模式起源于建筑领域,软件工程只有短短的几十年,与已经拥有几千年底蕴的建筑工程相比,后者有太多值得学习和借鉴的地方。哈佛大学的建筑学博士克里斯托弗.亚历山大,是建筑学领域的模式之父。他与其研究团队用了约20年的时间,对住宅和周边环境进行了大量的调查研究,发现人们对舒适住宅和城市环境存在一些共同的认同规律,将它们归纳成253个模式。对每一个模式都从前提条件、目标问题、 解决方案三个方面进行了描述,并给出了从需求分析到结构设计再到经典实例的过程模型。所以,对模式的定义可以抽象为在特定环境下,人们为了解决某类重复出现问题,而总结归纳出来的有效解决方案。
诞生
GoF将模式的概念引入软件工程领域,这标志着软件模式的诞生。软件模式并非仅限于设计模式,还包括架构模式、分析模式和过程模式等,实际上,在软件开发生命周期的每一个阶段都存在着一些被认同的模式。软件模式主要由四部分构成,包括待解决问题、约束条件、解决方案、优点。软件模式与具体的应用领域无关,也就是说无论从事的是移动开发、桌面开发、Web开发还是嵌入式软件的开发,都可以使用软件模式。在软件模式中,设计模式是研究最为深入的分支,它融合了众多专家的设计经验,已经在成千上万的软件中得以应用。 1995年, GoF将收集和整理好的23种设计模式汇编成了一本名叫《设计模式》的书,该书的出版也标志着设计模式正式成为面向对象版软件工程的一个重要研究分支。
参考文章【设计模式】软件模式起源与诞生http://blog.csdn.net/xiada_you_comeon/article/details/50418000
关联
面向对象是自上而下的设计方式,就像建筑设计,需要先有一个设计思想和方案,然后划分功能区域,再具体按照功能区域分布每个房间,再具体到房间中的陈列、装修;而函数式编程是自下而上的设计方式,就像建筑结构,需要使用小的结构点进行组合、拼装来实现一个完整的框架体系
设计模式概念与解读
概念
设计模式(Design Pattern)是一套被反复使用、多数人知晓、经过分类的、代码设计经验的总结。使用目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。
解读
在做不同类型的建筑设计时,需要遵守的相关建筑规范。它是一套健全、系统、经过时间沉淀的并且合法的准则。目的就是可以让建筑设计人员通过以上标准,高效、准确地设计出相关的建筑部件,以便组装成最后的成品建筑物。当然,计算机中的设计模式,在这基础上有进行也好多细化:
分类
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
设计模式的原则
总原则:开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。
1、单一职责原则
不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,如若不然,就应该把类拆分。
2、里氏替换原则(Liskov Substitution Principle)
里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
里氏替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。
3、依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。
4、接口隔离原则(Interface Segregation Principle)
这个原则的意思是:每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。
5、迪米特法则(最少知道原则)(Demeter Principle)
就是说:一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。
最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。
6、合成复用原则(Composite Reuse Principle)
原则是尽量首先使用合成/聚合的方式,而不是使用继承。
【关于工厂模式】
简单工厂(静态工厂)模式的概念
概念
工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。该模式使一个类的实例化延迟到了子类。而子类可以重写接口方法以便创建的时候指定自己的对象类型。
解读
简单来说,工厂模式是将实现同一事情的相同代码,放到一个函数中去,以后如果想再实现这个功能,都不需要重新编写这些代码了,只要执行当前的函数即可。
比如我们喝奶茶,如果世界上只有一个人想喝,那他自己做就好了,也不需要有奶茶店这种东西,但是随着想喝的人越来越多,制作奶茶的店也就慢慢开起来了。去买奶茶的人不需要知道制作过程,只需要关心我告诉店员的和他最后给我的是不是匹配的即可。
关系图
代码
function Juice(temperature,sugar,feeding){
var obj = {}
obj.temperature = temperature
obj.sugar = sugar
obj.feeding = feeding
obj.make = function(){
console.log('我要了一杯'+ this.temperature +',' + this.sugar + ','+ this.feeding +'的果汁')
}
return obj
}
let juice = Juice('热的','七分甜','加椰果')
juice.make()
抽象工厂模式
概念
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂,即“工厂的工厂”。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
解读
这个模式归根到底可以认为是子类将父类的对象复制,然后在子类中实现,这样的好处是相同的东西放到父节点里,子节点里负责特异化并实现抽象的内容,就可以生产出一堆东西
问题:emenent-ui 是不是使用了抽象工厂模式的的思想?
关系图
模型
生动的小视频
(没法上传本地视频)
动画可以点进去看哦,在页面的中下部位~
代码
function createAppleCake (){
console.log('我生产了苹果味蛋糕')
}
function createBananaCake (){
console.log('我生产了香蕉味蛋糕')
}
function createOrangeJuice (){
console.log('我生产了橘子汁')
}
function createLemonJuice (){
console.log('我生产了柠檬汁')
}
function getCake (name){
this.Cake = function (name){
console.log('我要生产蛋糕')
if(name === null) {
return null
}
if(name === 'apple') {
return new createAppleCake()
} else if (name === 'banana') {
return new createBananaCake()
}
}
}
function getJuice (name){
this.Juice = function (){
console.log('我要生产果汁')
if(name === null) {
return null
}
if(name === 'orange') {
return new createOrangeJuice()
} else if (name === 'lemon') {
return new createLemonJuice()
}
}
}
function FactoryProducer() {
this.getFactory = function (type) {
if(type === null) {
return null
}
if(type === 'cake') {
return new getCake()
} else if (type === 'juice') {
return new getJuice()
}
}
}
let producer = new FactoryProducer()
let cakeFactory = producer.getFactory('cake')
let cake = cakeFactory.Cake('apple')
工厂模式的使用时机和注意事项
使用时机
-
对象的构建十分复杂
-
需要依赖具体环境创建不同实例
-
处理大量具有相同属性的小对象
注意事项
不滥用运用工厂模式,有时候仅仅只是给代码增加了不必要的复杂度,同时使得开发难以继续下去。
给自己的思考
1、建筑设计和程序设计的关联性
2、建筑设计中是否还有可以提炼与借鉴的方法或模式来提高程序开发的效率?
生物(biology)+化学( chemistry) = 生化(biochemistry)
建筑(architecture)+ 编程(program) = ?(archiprogram)
3、意识和模式之间的关系:是意识创造了模式,还是模式在引导意识?
如果后人的受制来源于前人意识创造出来的模式,那么后人的模式是不是也会被先人的模式所限制?所以面对问题的时候,是不是需要打破这种模式的禁锢?
4、程序设计如何反哺建筑设计
5、程序开发的艺术性
本人之前是学建筑设计的,后面转行做了前端开发,以上的思考也是我在查找资料的过程中产生的,如果有感兴趣的同学可以进一步讨论与交流~~(有问题还望指出,谢谢)