面向对象程序设计(OOP:Object-oriented programming)是一种程序设计范型,同时也是一种程序开发的方法。对象指的是类的实例。
面向对象(Object Oriented,OO)是一种对现实世界理解和抽象的方法,是计算机编程技术[1] 发展到必定阶段后的产物。编程
面向对象的三大特色(封装,继承,多态)缺一不可。一般“基于对象”是使用对象,可是没法利用现有的对象模板产生新的对象类型,继而产生新的对象,也就是说“基于对象”没有继承的特色。而“多态”表示为运行时类型肯定(父类类型的子类对象实例),动态绑定执行对象,没有了继承的概念也就无从谈论“多态”。
示例:绘制一个图形,图形已有为三角形、圆;
Java 示例安全
// 父类:抽象、封装 public class Graph { void draw() { System.out.println("draw a Graph"); } }
// 继承:子类type1 public class Triangle extends Graph { @Override void draw() { System.out.println("draw a Triangle"); } } // 继承:子类type2 public class Circle extends Graph { @Override void draw() { System.out.println("draw a Circle"); } }
// 多态:运行时类型肯定 public class Drawer { static void draw(Graph a) { a.draw(); } // 运行调用 public static void main(String args[]) { Graph p = new Triangle(); Drawer.draw(p); // "draw a Triangle" p = new Circle(); Drawer.draw(p); //"draw a Circle" }
Javascript ES5示例闭包
// 封装 function Graph(){} Graph.prototype.draw = function (){ console.log("draw a Graph"); } // 原型链引用 function Trianggle(){} Trianggle.prototype = new Graph(); Trianggle.prototype.draw = function (){ console.log("draw a Trianggle"); } // 原型链引用 function Circle(){} Circle.prototype = new Graph(); Circle.prototype.draw = function (){ console.log("draw a Circle"); }
// 相对多态:无显示对象类型 function Drawer(obj){ obj.draw(); } // 运行时类型肯定 var p = new Trianggle(); Drawer(p); p = new Circle(); Drawer(p);
大多面向对象语言中,面向对象通常基于面向’类‘的设计。类是代码抽象的模式之一:实例化(instantiation)、继承(inheritance)、和 (相对)多态(polymorphism)。类和实例的关系比如房屋建造。建筑师会绘制建筑蓝图,建筑工人根据蓝图落地成实际建筑,建筑就是蓝图的复制(概念和物理上的复制)。类就是建筑的抽象,含有一个建筑的全部特性。实例就是实际的建筑,包含了门、窗以及实际材料、地理位置。类经过复制操做被实例化为对象形式,实例间无直接关系。但这没法直接对应到 JavaScript 的实现机制,由于 Javascript 没有实质类的概念,ES6的 class也是一种语法糖1。ide
面向对象编程强调的是数据和操做数据行为的的相互关联,所以最好的设计就是把数据和它相关的行为打包(封装)起来。
封装(Encapsulation)是指一种将抽象性函数式接口的实现细节部份包装、隐藏起来的方法。模块化
(1) 良好的封装能下降耦合度
(2) 方面数据统一管理、对象内部结构灵活修改
(3) 对其成员有更精确的控制,易于扩展
(4) 隐藏实现信息、细节,只暴露须要的 API函数
(1)工厂模式 - 函数 【内部对象建立属性方法并返回对象,使用this】this
function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); } return o; } var person1 = createPerson(“John”, 18, “Teacher"); var person2 = createPerson(“Greg”, 30, “Doctor”);
(2) 构造函数模式【内部 this建立属性、方法;无 return; 经过改变 this指向建立实例】prototype
**原生构造函数**:隐式建立对象,属性、方法赋值给 this对象,无 return;
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); } } var person1 = new Person(“John”, 18, “Teacher"); var person2 = new Person(“Greg”, 30, “Doctor”);
构造函数: new 显示建立 对象设计
步骤1: 建立一个新对象
步骤2:讲构造函数的做用是赋值给新对象 (this 只向新对象 词法做用域发生改变)
步骤3:执行构造函数的代码 (为新对象 添加属性 )
步骤4:返回新对象code
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); } }
构造函数做为函数; 问题:做用域改变,每一个传入的对象重建一遍;)
var person1 = new Object();
Person.call( person1, “John”, 18, “Teacher");
var person2 = new Person(“Greg”, 30, “Doctor”);
(3) 原型模式 【原型对象建立属性、方法】
构造函数无传参, 共享原型对象的属性,其中一个实例对原型对象的引用类型属性作修改,影响全部其余实例对该属性的使用; (* 引用类型属性受影响 内存分配机制不一样引发)
function Person(){} Person.prototype.name = 'Nicholas'; Person.prototype.age = 27; Person.prototype.job = 'Doctor'; Person.prototype.friends = ['Lily', 'John', 'Alex'] Person.prototype.sayName = function() { console.log(this.name); } Person.prototype.getFriends = function() { console.log(this.friends); }
var person1 = new Person(); person1.name = "person1"; var person2 = new Person(); person2.name = "person2"; person2.sayName(); //“person2" person2.getFriends(); // ["Lily", "John", "Alex"] person1.friends.push(“Van"); person1.sayName(); //“person1" person2.getFriends(); //["Lily", "John", "Alex", "Van"]
(4) 构造函数 & 原型模式结合 【构造函数独立属性方法,原型对象建立公用属性、方法】
好处:构造函数模式 定义实例个性化属性;原型模式定义方法和共享属性;功能模块化 职责单一
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = [‘Lily', 'John', 'Alex']; } Person.prototype ={ constructor: Person, sayName: function(){ alert(this.name); } } var person1 = new Person("Nicholas", 29, "Software Engineer"); person1.friends.push('Van'); var person2 = new Person(“Greg", 27, "Doctor");
(5) 动态原型模式 (使用:功能模块化)【构造函数独立属性方法,原型对象按需建立公用属性、方法】
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = [‘Lily’, 'John', 'Alex']; if(typeof this.sayName != ‘function’){ Person.prototype.sayName = function(){ alert(this.name); }; } }
(6) 寄生构造函数模式 -【 已有对象扩展 - 原型链 】 (使用:第三方库扩展 )
1.写法上和工厂模式同样 调用时多加 new 2.此模式建立的对象 与构造函数无关系, instanceof操做符无心义
function Person(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); } return o; } // 工厂模式 // var person1 = Person(“John”, 18, “Teacher”); // 寄生模式 var friend = new Person(“John”, 18, “Teacher”); // 返回新对象的实例
(7) 稳妥模式 【 内部建对象不用 this 闭包 - 词法做用域 】(稳妥对象-无公共属性,方法不引用 this)(使用:适用于安全环境 - 禁用 this 和 new)
1.写法上和寄生模式相似 , 除方法不使用 this 2.此模式建立的对象 与构造函数无关系, instanceof操做符无心义
function Person(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(name); //无 this } return o; } var friend = Person(“John”, 18, “Teacher”); //无 new