精华内容
下载资源
问答
  • 深入理解对象 之创建对象: 工厂模式: 工厂模式虽然解决了创建\多个相似...js中可以自定义构造函数,从而自定义对象类型的属性和方法,构造函数本身也是函数,只不过可以用来创建对象 构造函数的问题 每...

     

    深入理解对象 之创建对象

     

    工厂模式:

    工厂模式虽然解决了创建\多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)

    工厂模式问题那就是识别问题,因为根本无法 搞清楚他们到底是哪个对象的实例。

     

     

    构造函数模式

    js中可以自定义构造函数,从而自定义对象类型的属性和方法,构造函数本身也是函数,只不过可以用来创建对象

     

    构造函数的问题

    每个方法都需要在每个实例上重新创建一遍,但是毫无必要。

    可以在全局范围中声明一个函数,然后将引用传递给对象中的函数属性。但是这样做会导致全局函数过多,体现不了对象的封装性

     

    创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型;而这正是构造函数模式胜过工厂模式的地方。

     

     

    原型模式:

    每个函数都有一个属性:prototype(原型属性),这个属性是一个指针,指向一个对象,该对象的用途是包含原型模式:

    由特定类型的所有实例共享的属性和方法

    每个函数都有一个属性:prototype(原型属性),这个属性是一个指针,指向一个对象,该对象的用途是包含可以由特定类型的所有实例共享的属性和方法

     

     

    原生模式问题:

    所有实例在默认情况下都将取得相同的属性值,这种共享对于函数来说非常合适,但是包含引用数据类型的值就不太好(一改都改)

     

     

    组合使用构造函数模式和原型模式

     

     

     

     

    Constructor属性和prototype属性的关系:

    创建了自定义的构造函数之后,其原型对象默认会取得constructor属性;当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。(指向的是原型对象而不是构造函数)

    每个函数都有一个属性:prototype(原型属性),这个属性是一个指针,指向一个(原型)对象,该对象的用途是包含可以由特定类型的所有实例共享的属性和方法

     

    解释:函数里都有prototype属性,指向prototype对象,prototype对象有constructor属性,默认指向原函数,继承之后可以通过修改这些属性的指向来实现继承关系!

     

     

     

    附加:

    构造函数是一种特殊的函数:

    1,可以用普通方式去调用 函数名();

    就不会有创建对象等等过程

    2,用 new 去调用

    new操作符调用构造函数创建对象实际上经历了如下几个步骤

     

    1) 创建一个新对象

    2) 将构造函数的作用域赋给新对象(this指向这个新对象)

    3) 执行构造函数中的代码

    4) 返回新对象。

     

    //new 之后如果是函数的运行 函数名();,优先new操作

    new Person('zhangsan').sayName();

     

    //Person.sayName看做一个整体去使用new,会运行Person.sayName函数里面的东西,同时返回一个新对象,新对象的类型Person.sayName

    new Person.sayName();   //先运行方法,再new

    转载于:https://www.cnblogs.com/wskb/p/11089662.html

    展开全文
  • Object构造函数、对象字面量、Object.creat都可以用来创建单个对象,但有明显缺点:使用同一个接口创建很多对象,会产生大量的重复代码。所以才开始了创建对象的模式的探索。 检测对象的类 3种常见的检测任意对象的...

    起因

    Object构造函数、对象字面量、Object.creat都可以用来创建单个对象,但有明显缺点:使用同一个接口创建很多对象,会产生大量的重复代码。所以才开始了创建对象的模式的探索。

    检测对象的类

    3种常见的检测任意对象的类的技术:instanceof运算符、constructor属性、构造函数的名字。3种各有优劣,适用于不同场景。(但往往我们更关注对象可以完成什么工作,对象属于哪个类并不是最重要的)

    1. instanceof运算符

      运算符左边是对象,右边是构造函数,如o instanceof f,如果在o的原型链中查找到f,就返回true:

    var date = new Date();
    console.log(date instanceof Date);//true
    console.log(date instanceof Object);//true
    console.log(date instanceof Number);//false
    复制代码

    这种方式的缺点:①无法通过对象来获得类名,只能检测对象是否属于指定的类名,②如果是不同的执行上下文,如客户端中每个窗口和框架子页面都具有单独的执行上下文,其中一个框架页面中的数组不是另一个框架页面的Array()构造函数的实例。

    1. constructor属性
    console.log(date.constructor == Date);//true
    复制代码

    缺点:①和instance的第2点缺点一样,执行上下文的问题,②并不是所有的对象都有constrctor属性,如果创建对象时把对象的prototype直接覆盖了而又没有指定constrctor属性,就会没有这个属性。

    1. 构造函数的名称
    //返回对象的类
    function classof(o) {
        return Object.prototype.toString.call(o).slice(8,-1);
    }
    //返回函数的名字(可能是空字符串),不是函数就返回null
    Function.prototype.getName = function () {
        if("name" in this) return this.name;
        return this.name = this.toString().match(/function\s*([^()]*)\(/)[1];
    }
    function type(o) {
        //type,class,name
        var t,c,n;
    
        //处理null值特殊情况
        if(o === null) return 'null';
        //处理NaN和它自身不相等
        if(o !== o) return "nan";
        //识别出原始值的类型
        if((t = typeof o) !== "object") return t;
        //识别出大多数的内置对象(类名除了"Object"if((c=classof(o)) !== "Object") return c;
        //如果对象构造函数的名字存在,就返回它
        if(o.constructor && typeof o.constructor === "function" && (n = o.constructor.getName()) ) return n;
        //其他的类型无法判别,返回"Object"
        return "Object";
    }
    复制代码

    这种方法的问题:①并不是所有的构造函数都有constructor属性,②并不是所有的函数都有名字(name是非标准属性),如果使用不带名字的函数定义表达式定义一个构造函数,getName()方法会返回空字符串。

    //这种情况下如果没有name属性,那么getName()方法就返回空字符串了
    var Example = function (x, y) {
        this.x = x;this.y = y;
    }
    复制代码

    1.工厂模式

    function creatPerson(name, age, job) {
        var o = new Object();
        o.name = name;
        o.age = age;
        o.job = job;
        o.sayName = function () {
            console.log(this.name);
        };
        return o;
    }
    var person1 = creatPerson('jaychou',34,'singer');
    var person2 = creatPerson('xiaoming',15,'student');
    //{name: "jaychou", age: 34, job: "singer", sayName: ƒ}
    console.log(person1);
    //{name: "xiaoming", age: 15, job: "student", sayName: ƒ}
    console.log(person2);
    复制代码

    工厂模式的最大缺点:没有解决对象识别的问题,不知道一个对象的类型。

    2.构造函数模式

    显然构造函数可用来创建特定类型的对象,如Array,Date等,重写上面的例子:

    function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.sayName = function () {
            console.log(this.name);
        }
    }
    //{name: "jaychou", age: 34, job: "singer", sayName: ƒ}
    var person1 = new Person('jaychou',34,'singer');
    //{name: "xiaoming", age: 15, job: "student", sayName: ƒ}
    var person2 = new Person('xiaoming',15,'student');
    复制代码

    与之前对比:①没有显式地创建对象,②直接将属性和方法赋给了 this 对象,③没有 return 语句

    使用new操作符调用Person构造函数后:

    • 创建一个新对象
    • 将构造函数的作用域赋给新对象(this指向了这个新对象)
    • 执行构造函数中的代码(为新对象添加属性和方法)
    • 返回新对象

    类型的标识有了,构造函数模式的主要缺点是:每个方法都要在每个实例上重新创建一遍(函数也是对象的一种,导致重复创建对象了)

    3.原型模式

    1. 基本
    function Person() {
    
    }
    Person.prototype.name = "jaychou";
    Person.prototype.age = 34;
    Person.prototype.job = 'singer';
    Person.prototype.sayName = function () {
        console.log(this.name);
    }
    var person1 = new Person();
    person1.sayName();//jaychou
    var person2 = new Person();
    person2.sayName();//jaychou
    console.log(person1.sayName == person2.sayName);//true
    复制代码

    创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。

    //{name: "jaychou", age: 34, job: "singer", sayName: ƒ, constructor: ƒ}
    console.log(Person.prototype);
    复制代码

    我们打印了Person.prototype,默认情况下会有一个constructor属性,这个属性指向函数(在这里就是指向构造函数),其他的name,age,job,sayName属性和方法都是通过Person.prototype.**添加进去的,所以由构造函数Person创建的实例都会包含这些属性和方法,它们是共享的。

    而且实例的内部包含一个指针(内部属性),指向构造函数的原型对象:[[Prototype]],在Firefox、Safari和Chrome中支持属性__proto__:

    //{name: "jaychou", age: 34, job: "singer", sayName: ƒ, constructor: ƒ}
    console.log(person1.__proto__);
    console.log(Person.prototype == person1.__proto__);//true
    
    //打印对象的constructor:在这里person1的constructor就是Person
    console.log(person1.constructor == Person);//true
    复制代码

    另外,可以通过 isPrototypeOf 方法来确定对象之间是否存在原型关系:

    console.log(Person.prototype.isPrototypeOf(person1));//true
    复制代码

    还有,可以通过 Object.getPrototype 返回对象的原型:

    //打印对象的原型:{name: "jaychou", age: 34, job: "singer", sayName: ƒ, constructor: ƒ}
    console.log(Object.getPrototypeOf(person1));
    console.log(Object.getPrototypeOf(person1).name);//jaychou
    复制代码

    之前也有提及,查询属性和方法时先在当前实例中找,没有的话就到实例的原型链中找,而在实例中添加的属性会屏蔽原型中的同名属性。

    1. 更简单的原型语法

    上一个例子中每增加一个属性和方法就要敲一遍Person.prototype,比较麻烦,所以更简单的做法是用一个包含所有属性和方法的对象字面量来重写整个原型对象:

    Person.prototype = {
        name:'jaychou',
        age:34,
        job:'singer',
        sayName:function () {
            console.log(this.name);
        }
    }
    var person3 = new Person();
    console.log(Person.prototype.constructor == Person);//false
    console.log(Person.prototype.constructor == Object);//true
    console.log(person3.constructor == Person);//false
    console.log(person3.constructor == Object);//true
    复制代码

    上面的代码将 Person.prototype设置为等于一个以对象直接量形式创建的新对象,结果就导致了constructor 属性不再指向 Person 了,因为本质上完全重写了默认的prototype对象,因此constructor 属性也就变成了新对象的constructor属性(指向Object构造函数),不再指向 Person函数。看下面的例子就更清楚了:

    function Teacher(){
    
    };
    var tea1 = new Teacher();
    Person.prototype = tea1;
    //true:因为Person.prototype被重写成tea1,tea1的constructor自然指向了Teacher构造函数
    console.log(Person.prototype.constructor == Teacher);
    复制代码

    所以,如果constrctor的值很重要,可以在上面代码的基础上手动加回去,最好仿照原生的把constructor属性设置成不可枚举的:

    Object.defineProperty(Person.prototype, "constructor", {
        enumerable: false,
        value: Person
    });
    console.log(Person.prototype.constructor == Person);//true    
    复制代码

    注意一个问题: 如果某个实例已经被创建了之后,再直接重写了构造函数的原型对象,那么之前已被创建好的对象内部的原型指针还是指向旧的原型,如果旧实例调用了新原型里面定义的方法,就会报错了。所以重写函数的原型对象时要特别注意这个问题。

    1. 原型对象模式的问题

    以上的创建对象在原型里共享了所有的属性和方法,对于方法还好,对于大多数情况下属性共享带来的问题就显而易见了。

    4.组合使用构造函数模式和原型模式

    创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。

    function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
    }
    Person.prototype = {
        constructor:Person,
        sayName:function () {
            console.log(this.name);
        }
    }
    var person1 = new Person('jaychou',34,'singer');
    var person2 = new Person('xiaoming',15,'student');
    person1.sayName();//jaychou
    person2.sayName();//xiaoming
    console.log(person1.sayName === person2.sayName);//true
    复制代码

    5.动态原型模式(最常用)

    对上面的例子进行视觉上的美化,希望把所有的内容都放在构造函数里面,可以通过检查某个应该存在的方法或属性是否存在,来决定是否需要初始化原型:

    function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
    
        //添加共享的方法或属性
        if(typeof this.sayName != "function"){
            Person.prototype.sayName = function () {
                console.log(this.name);
            };
            Person.prototype.sayJob = function () {
                console.log(this.job);
            }
        }
    }
    复制代码

    注意: 使用动态原型模式时,不能使用对象直接量重写原型,原因上面已经解释过了,重写会切断了旧实例和新原型之间的联系。

    转载于:https://juejin.im/post/5b7842d2f265da431e7b768f

    展开全文
  • Bean 管理操作有两种方式 一种是:xml配置文件方式 一种是:基于注解方式实现 IOC操作Bean管理注解方式(创建对象) ...以下四个注解功能是一样的,都可以用来创建bean实例,且不分用在哪个层 ...

    目录

     IOC操作Bean管理注解方式(创建对象)

    1.什么是注解

    2.Spring 针对 Bean 管理中创建对象提供注解主要有以下四种

    (1)@Component

    (2)@Service

    (3)@Controller

    (4)@Repository

    3.基于注解方式实现对象的创建

    步骤一:搭建项目

    步骤二:引入aop依赖

    步骤三:开启组件扫描

    步骤四:创建类,在类上面创建对象进行注解

    步骤五:测试


     

     

     

    Bean 管理操作有两种方式

    一种是:xml配置文件方式

    一种是:基于注解方式实现

     

     IOC操作Bean管理注解方式(创建对象)

     

    1.什么是注解

    概念:注解是代码的 特殊标记 

    格式:@注解名称(属性名称1=属性值,属性名称2=属性值......)

    使用:注解作用在类上面、方法上面、属性上面

    目的:简化xml配置

     

    2.Spring 针对 Bean 管理中创建对象提供注解主要有以下四种

    以下四个注解功能是一样的,都可以用来创建bean实例,且不分用在哪个层

    (1)@Component

    (2)@Service

    (3)@Controller

    (4)@Repository

    @Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法。通俗来说,被Controller标记的类就是一个控制器,这个类中的方法,就是相应的动作。
    1、@controller 控制器(注入服务)
    2、@service 服务(注入dao)
    3、@repository dao(实现dao访问)
    4、@component (把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>)

     

    3.基于注解方式实现对象的创建

     

    步骤一:搭建项目

     

    步骤二:引入aop依赖

    首先,找到依赖,在之前下载的Spring的jar包中找到aop jar包

     

    然后,引入jar包到项目中

     

    步骤三:开启组件扫描

    组件扫描:告诉Spring容器,现在要到哪个类里面去注解,那么就需要扫描这些类,才能进行对象的创建

    结构: 

     

    bean1.xml的代码如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!--上面是名称空间引入-->
    
        <!--开启组件扫描-->
    
            <!--1.如果要扫描多个包 ,要用逗号“,”隔开-->
        <!--<context:component-scan base-package="com.lbj.spring5.service,com.lbj.spring5.dao"></context:component-scan>-->
    
            <!--2.也可以扫描包的上一级-->
        <context:component-scan base-package="com.lbj.spring5"></context:component-scan>
    </beans>

     

    步骤四:创建类,在类上面创建对象进行注解

    在 service 包内创建一个 UserService 类

    注意:在注解里面 value 的属性值可以省略不写,value的默认值是类的首字母小写的名称

    如:类名是UserService  等价于 value="userService"

    UserService 类代码如下:

    package com.lbj.spring5.service;
    
    import org.springframework.stereotype.Component;
    //开启注解
    //在xml配置中 id的含义和此处的value的含义一致
    @Component(value = "userService")
    public class UserService {
    
        public void add(){
            System.out.println("UserService is open");
        }
    }
    

     

    步骤五:测试

    package com.lbj.spring5.testdemo;
    
    
    import com.lbj.spring5.service.UserService;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    
    public class TestSpring5Demo1 {
        @Test
        public void testService01(){
            ApplicationContext context
                    =new ClassPathXmlApplicationContext("bean1.xml");
    
            UserService userService = context.getBean("userService", UserService.class);
    
            System.out.println(userService);
    
            userService.add();
    
        }
    
    }
    

     

     

     

    展开全文
  • 实现Runnable接口更好一些。 1,因为实现Runnable接口可以避免Java单继承的局限性。 当一个类继承了Thread,就不可以在继承其他类了。 ...而当一个类实现了Runnable,它一样可以继承其他类...run()方法的作用是用来封装
    实现Runnable接口更好一些。

    1,因为实现Runnable接口可以避免Java单继承的局限性。
    当一个类继承了Thread,就不可以在继承其他类了。
    而当一个类实现了Runnable,它一样可以继承其他类。
    比如 class Demo extends SuperDemo implements Runnable{}

    2,更符合面向对象的设计。
    run()方法的作用是用来封装线程要运行的代码。
    那么run()方法所属的对象,就是线程任务对象。
    Thread类的子类对象即使线程对象,又是线程任务对象。耦合性很强。
    有了Runnable接口,可以将线程任务和线程进行解耦,
    提高了程序的扩展性。
    展开全文
  • 什么是单例对象 ...object里面定义的是静态方法,scala没有静态的概念,通过单例对象可以用来定义main方法 object相当于工具类,用来定义静态方法和常量 单例对象中不可以携带参数,因为都不需要创建对象 o...
  • 封装一个函数 , 用来创建对象并给对象中特定的属性添加值 , 优点是可以循环调用 , 缺点是每一个创建出来的对象都是独立的 , 不能确定它是哪个类型的对象 ( 或者说是想要将哪个对象作为模板进行创建 ) function func...
  • 1、Connection:是创建链接对象的类,是执行数据库操作的必要操作。...2、Command:主要可以用来对数据库发出一些指令,例如可以对数据库下达查询、新增、修改、删除数据等指令,以及呼叫存在数据库中的预存程序等...
  • 简单工厂模式是由一个方法来决定到底要创建哪个类的实例,而这些实例经常都拥有相同的接口。...用简单工厂来创建对象可以减少全局变量创建提高代码复用率,它的使用场合限制在创建单一对象。 ...
  • 成员方法属于哪个对象,“$this”就代表哪个对象,与连接符->联合使用,专门用来完成对象内部成员之间的访问。如下所示:$this -> 成员属性;$this -> 成员方法(参数列表);比如在 Website 类中有一个 $name ...
  • 成员方法属于哪个对象,“$this”就代表哪个对象,与连接符->联合使用,专门用来完成对象内部成员之间的访问。如下所示:$this -> 成员属性;$this -> 成员方法(参数列表);比如在 Website 类中有一个 $name ...
  •  (2)使用类名创建对象时(为对象在内存中分配空间),自动调用初始化方法为对象的属性设置初始值  (3)self.属性名 = 属性值 其他对象不需要再次定义该属性,就可以拥有该属性,任何方法都可以使用该属性  (4)在...
  • 1、Connection:是创建链接对象的类,是执行数据库操作的必要操作。该类的对象连接帮助指明...2、Command:主要可以用来对数据库发出一些指令,例如可以对数据库下达查询、新增、修改、删除数据等指令,以及呼叫存...
  • type 获取 当前的对象是又哪个创建的 还可以导入 from types import Functiontype,Methodtype from types import FunctionType,MethodTypeisinstance(a,b)是检查第一个参数是都是第二个参数(类及父类)的实例用...
  • 说到Python和PHP,PHP 是一种创建动态交互性站点的强有力的服务器端脚本语言,一般用来做网站的服务器后端语言使用,而Python是一种解释型、面向对象、动态数据类型的高级程序设计语言,之前一般用作数据统计分析,...
  • 这个库被创建用来在服务器端进行图像处理。使用这个图像库允许你用一个简单的方法进行复杂的图像处理。可对图像进行的操作,包括旋转,裁剪,缩放,拉伸和翻转。而您只需要通过一堆代码就可以...
  • 在面向对象程序设计中,工厂是一个用来创建对象的对象,是构造方法的抽象。 工厂对象一般拥有多个创建对象的方法,工厂对象可以通过参数动态创建类,可以针对不同的创建对象,进行特殊的配置。 下列情况可以考虑...
  • B final类不但可以用来派生子类,也可以用来创建final类的对象。 C abstract不能与final同时修饰一个类。 D abstract类定义中可以没有abstract方法。 1、abstract类不能用来创建abstract类的对象;抽象类和...
  • 可以用来保存到数据库中,相反,登录的时候,因为MD5加密是不可逆的运算,只能拿用户输入的密码走一遍MD5+salt加密之后, 跟数据库中的password比较,看是否一致,一致时密码相同,登录成功,通过调用HexUtil....
  • abstract类

    2019-06-19 14:41:01
    B final类不但可以用来派生子类,也可以用来创建final类的对象。 C abstract不能与final同时修饰一个类。 D abstract类定义中可以没有abstract方法。 正确答案:A C D 1、abstr...
  • 工厂模式

    2017-09-23 10:47:44
    工厂模式是一个在软件开发中用来创建对象的设计模式。 工厂模式包涵一个超类。这个超类提供一个抽象化的接口来创建一个特定类型的对象,而不是决定哪个对象可以被创建。 为了实现此方法,需要创建一个工厂类...
  •  工厂模式是一个在软件开发中用来创建对象的设计模式。  工厂模式包涵一个超类。这个超类提供一个抽象化的接口来创建一个特定类型的对象,而不是决定哪个对象可以被创建。  为了实现此方法,需要创建一个工厂类...
  • Java常见易错题3

    2018-12-12 20:13:55
    final类不但可以用来派生子类,也可以用来创建final类的对象。 C. abstract不能与final同时修饰一个类。 D. abstract类定义中可以没有abstract方法。 解析: 选 ACD A,抽象类和接口都不可以实例化。 B,final类不...
  • python 模式之工厂模式

    2019-10-08 09:47:51
    工厂模式是一个在软件开发中用来创建对象的设计模式。 工厂模式包涵一个超类。这个超类提供一个抽象化的接口来创建一个特定类型的对象,而不是决定哪个对象可以被创建。 为了实现此方法,需要创建一个工厂类创建并...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 189
精华内容 75
关键字:

哪个可以用来创建对象