精华内容
下载资源
问答
  • 设计模式 - 创建型设计模式 - 原型模式(Java)

    万次阅读 多人点赞 2019-02-19 19:51:19
    请点击http://www.captainbed.net 这是要说的创建型模式的最后一个设计模式了。 原型模式很简单:有一个原型实例,基于这个原型实例产生新的实例,也就是“克隆”了。 Object 类中有一个 clone() 方法,它用于生成...

    分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请点击http://www.captainbed.net 

    这是要说的创建型模式的最后一个设计模式了。

    原型模式很简单:有一个原型实例,基于这个原型实例产生新的实例,也就是“克隆”了。

    Object 类中有一个 clone() 方法,它用于生成一个新的对象。当然,如果我们要调用这个方法,Java 要求我们的类必须先实现 Cloneable 接口,此接口没有定义任何方法,但是不这么做的话,在 clone() 的时候,会抛出 CloneNotSupportedException 异常。

    protected native Object clone() throws CloneNotSupportedException;

    Java 的克隆是浅克隆,碰到对象引用的时候,克隆出来的对象和原对象中的引用将指向同一个对象。通常实现深克隆的方法是将对象进行序列化,然后再进行反序列化。

    个人觉得原型模式了解到这里就够了,各种变着法子说这种代码或那种代码是原型模式,没什么意义。

    展开全文
  • 【面向对象】——设计模式之创建型模式

    千次阅读 热门讨论 2014-12-23 14:52:15
    创建型模式创建型模式抽象了实例化的过程。它们帮助一个系统独立于如何创建、组合和表示它的那些对象创建型模式都会讲关于该系统使用哪些具体的类的信息封装起来。允许客户用结构和功能差别很大的“产品”对象...


    创建型模式:创建型模式抽象了实例化的过程。它们帮助一个系统独立于如何创建、组合和表示它的那些对象。创建型模式都会讲关于该系统使用哪些具体的类的信息封装起来。允许客户用结构和功能差别很大的“产品”对象配置一个系统。配置可以是静态的,即在编译时指定,也可以是动态的,就是运行时再指定。

    创建型模式包括:工厂方法,抽象工厂,建造者,原型,单例。

    工厂方法:

    定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。


    工厂方法模式,完全符合了开放-封闭原则。较简单工厂而言,工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。当想要加功能时,本来改工厂类,现在只需改客户端。更加符合了开放-封闭原则。


    抽象工厂:

    提供一个创建一系列或相关依赖对象的接口,而无需指定它们具体的类。


    这个例子是解决不能换数据库问题的。当换数据库时,用代码直接切换数据库工厂即可,而不需更改大量代码。很好的实现了开放-封闭原来,和依赖倒转原则。

    抽象工厂模式便于交换产品系列,由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。另,它让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。


    单例模式:

    保证一个类仅有一个实例,并提供一个访问它的全局访问点。


    通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。


    原型模式:

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。


    原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节。其实,原型模式就相当于克隆,建一个实现模型的接口,便可克隆对象了。并且建立相应数目的原型并克隆它们通常比每次用合适的状态手工实例化该类方便很多。


    建造者:

    将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。


    建造者模式,主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。符合了合成/聚合复用原则。

    如果你需要将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示的时候,我们就需要创建者模式,将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。如果用了建造者模式,那么用户就只需要指定需要的建造的类型就可以得到他们,而具体建造的过程和细节就不需要了。


    总:通常设计是从工厂方法开始,当设计者发现需要更大的灵活性时,设计便会向其他创建型模式演化,当设计者在设计标准间进行权衡的时候,了解多个创建型模式可以给设计者更多的选择余地。

    展开全文
  • UML、对象创建型模式

    万次阅读 2019-12-03 21:02:20
    是类与类之间最常用的一种关系, 它是一种结构化关系,用于表示一类对象与另一类对象之间有联系。 单线实箭头,可自关联 关联关系中要表明对象间的关联关系,如是一对多还是一对一 依赖关系(Dependency) 一种使用...

    UML

    关联关系(Association)

    是类与类之间最常用的一种关系, 它是一种结构化关系,用于表示一类对象与另一类对象之间有联系。

    单线实箭头,可自关联

    关联关系中要表明对象间的关联关系,如是一对多还是一对一

    依赖关系(Dependency)

    一种使用关系,例如类A的某个方法需要类B做参数,即要使用类B的方法,用虚线表示

    聚合关系(Aggregation)

    表示一个整体与部分的关系,成员类是整体类的一部分,即成员对象是整体对象的一部分,但是成员对象可以脱离整体对象独立 存在。聚合关系用带空心菱形的直线表示。

    组合关系(Composition)

    也表示类之间整体和部分的关系, 但是组合关系中部分和整体具有统一的生存期。一旦整体对象不存在,部分对象也将不存在,部分对象与整体对象之间具有同生共死的关系。 如必须传递某个构造器参数以初始化类,用实心菱形的直线表示。

    泛化关系(Generalization)

    就是继承关系,用带空心三角形的直线来表示。

    实现关系(Realization)

    接口与实现的关系,用带空心三角形的虚线来表示。

    设计模式

    对象创建型模式

    面向对象设计原则

    QnGkdA.md.png

    工厂方法模式

    产品对象通过公共接口实现功能,抽象工厂声明工厂方法由具体子类去实现,工厂的目的是为了返回产品,抽象工厂声明的方法要返回抽象产品,每一个具体产品都对应有一个具体工厂,具体工厂返回具体产品,利用多态的性质,全程使用接口对象声明即可。

    模式结构

    • Product:抽象产品,产品对象的共同父类或接口

    • ConcreteProduct:具体产品 ,实现了抽象产品接口

    • Factory:抽象工厂,声明工厂方法,交给子类实现

    • ConcreteFactory:具体工厂,实现抽象工厂中的工厂方法,返回一个具体产品类的实例

    image.png

    利用多态的性质,将通用方法抽象出来放在接口中,调用时更加灵活

    所有的具体工厂类都具有同一抽象父类。在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

    public interface Log {
        void writeLog();
    }
    public class FileLog implements Log {
        @Override
        public void writeLog(){
            System.out.println("我是文件日志写入器");
        }
    }
    public class DataBaseLog implements Log {
        @Override
        public void writeLog(){
            System.out.println("我是数据库日志写入器");
        }
    }
    
    public interface AbstractLogFactory {
        Log createLog();
    }
    public class FileLogFactory implements AbstractLogFactory{
        @Override
        public Log createLog(){
            return new FileLog();
        }
    }
    public class DataBaseLogFactory implements AbstractLogFactory {
        @Override
        public Log createLog(){
            return new DataBaseLog();
        }
    }
    
    public class FactoryMethodPatternTest {
        public static void main(String[] args){
            AbstractLogFactory abstractLogFactory;
    
            abstractLogFactory=new FileLogFactory();
            abstractLogFactory.createLog().writeLog();
    
            abstractLogFactory=new DataBaseLogFactory();
            abstractLogFactory.createLog().writeLog();
        }
    }
    

    运行结果为:

    我是文件日志写入器
    我是数据库日志写入器
    

    抽象工厂模式

    弥补工厂方法模式每一种产品都需要新增具体工厂的不足,抽象工厂中声明多种产品工厂方法,能为一个产品家族返回多种属于该家族的具体产品。

    当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。

    模式结构:

    • AbstractFactory:抽象工厂

    • ConcreteFactory:具体工厂

    • AbstractProduct:抽象产品

    • Product:具体产品

    同样利用多态性质,符合开闭原则

    public interface Connection {
        boolean connection(String url,int port,String password);
    }
    public class OracleConnection implements Connection{
        @Override
        public  boolean connection(String url,int port,String password){
            System.out.println("已连接:"+url+port);
            return true;
        }
    }
    public class MySqlConnection implements Connection{
        @Override
        public  boolean connection(String url,int port,String password){
            System.out.println("已连接:"+url+port);
            return true;
        }
    }
    
    public interface Statement {
        boolean getStatement();
    }
    public class OracleStatement implements Statement {
        @Override
        public  boolean getStatement(){
            System.out.println("create Oracle Statement");
            return true;
        }
    }
    public class MySqlStatement implements Statement {
        public  boolean getStatement(){
            System.out.println("create MySql Statement");
            return true;
        }
    }
    
    public interface AbstractFactory {
        Connection createConnection();
        Statement createStatement();
    }
    public class OracleFactory implements AbstractFactory{
        @Override
        public Connection createConnection(){
            return new OracleConnection();
        }
        @Override
        public Statement createStatement(){
            return new OracleStatement();
        }
    }
    public class MySqlFactory implements AbstractFactory {
        @Override
        public Connection createConnection(){
            return new MySqlConnection();
        }
        @Override
        public Statement createStatement(){
            return new MySqlStatement();
        }
    }
    

    同样使用多态的性质,如果使用工厂方法模式,那么就需要建造两个抽象工厂,四个具体工厂,因为两个抽象产品属于同一个产品家族,所以只使用一个抽象工厂,把生产工厂的方法放在一起即可。缺点是难以扩展抽象产品,因为必须属于同一产品族的产品才可以加入,为了达到单一职责原则,不能在抽象工厂中任意添加产品

    建造者模式

    将部件和其组装过程分开,一步一步创建一个复杂的对象。即将一个复杂对象的构建与它的表示分离。

    也可能存在多个基本部分对象,基本部分对象通过不同的组合可以构建不同的对象,用户使用不同的具体建造者即可得到不同的产品对象。

    模式结构

    • Director:指挥者 ,用于实际生产产品,内部有方法construct,规定一个产品的构造顺序(即如何构造),通过对基本对象的组合生成一个复杂产品,内部维护建造者Builder,通过construct按顺序建造产品

    • Builder:抽象建造者 ,规定建造所有基本对象的方法

    • ConcreteBuilder:具体建造者,实现每部分的建造方法

    • Product:产品角色

    建造者模式的目的仍然是为了解耦,屏蔽某些复杂产品的实现,生成产品的组件由接口声明,由具体的建造者建造,由Director调用组件组合顺序生成产品,允许用户只通过指定复杂对象的类型和内容就可以构建它们, 用户不需要知道内部的具体构建细节。

    //产品及组件
    public class Product {
        private ComponentA componentA;
        private ComponentB componentB;
        public Product(ComponentA componentA,ComponentB componentB){
            this.componentA=componentA;
            this.componentB=componentB;
        }
        @Override
        public String toString(){
            return "我是产品";
        }
    }
    
    public class ComponentA {
        @Override
        public String toString(){
            return "我是组件A";
        }
    }
    
    public class ComponentB {
        @Override
        public String toString(){
            return "我是组件B";
        }
    }
    
    //建造者及实现
    public interface Builder {
        ComponentA buildA();
        ComponentB buildB();
    }
    public class ConcreteBuilder implements Builder{
        @Override
        public ComponentA buildA(){
            System.out.println("创建组件A");
            return new ComponentA();
        }
        @Override
        public ComponentB buildB(){
            System.out.println("创建组件B");
            return new ComponentB();
        }
    }
    
    //指挥者,规定产品组合顺序,调用建造者组装成产品并返回
    public class Director {
        public static Product buildProduct(){
            Builder builder=new ConcreteBuilder();
            return new Product(builder.buildA(),builder.buildB());
        }
    }
    public class builderPatternTest {
        public static void main(String[] args){
            Product product=Director.buildProduct();
            System.out.println(product.toString());
        }
    }
    /*运行结果
    创建组件A
    创建组件B
    我是产品
    */
    

    原型模式

    对象创建型模式,用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象

    在原型模式结构中定义了一个抽象原型类,所有的Java类都继承 自java.lang.Object,而Object类提供一个clone()方法,可以将 一个Java对象复制一份。因此在Java中可以直接使用Object提供的clone()方法来实现对象的克隆,Java语言中的原型模式实现很简单。 能够实现克隆的Java类必须实现一个标识接口Cloneable,表示这个Java类支持复制。如果一个类没有实现这个接口但是调用了 clone()方法,Java编译器将抛出一个 CloneNotSupportedException异常。

    浅克隆只克隆同一份对象的域的引用,深克隆开辟新的空间并赋值

    java中的clone()是深克隆,但copy的内存中如果有引用变量,那么引用的仍然是同一块空间,如果想让引用变量引用的空间也克隆一份,那么最好重写clone()或者自己另写一个创建原型的方法

    import java.util.Properties;
    public class PrototypePatternTest {
        public static void main(String[] args){
            Properties properties=new Properties();
            properties.put("a",new Properties());
            Properties propertiesClone=(Properties) properties.clone();
    
            System.out.println(properties==propertiesClone);
            System.out.println(properties.getClass()==propertiesClone.getClass());
            
            //clone的对象引用新的空间
            properties.put("b",2);
            System.out.println(propertiesClone.get("b"));
            
            //但是内部的引用变量仍然引用同一块空间
            ((Properties)properties.get("a")).put("b","2");
            System.out.println(((Properties)propertiesClone.get("a")).get("b"));
        }
    }
    /*结果为
    false
    true
    null
    2
    */
    

    使用原型模式可以简化对象的创建过程,通过一个已有实例可以提高新实例的创建效率。

    单例模式

    单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

    单例模式的要点有三个:一是某个类只能有一个实例; 二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。

    模式结构

    • Singleton:单例

    单例类拥有一个私有构造函数,确保用户无法通过new关键字直接实例化它。除此之外,该模式中包含一个静态私有成员变量与静态公有的工厂方法,该工厂方法负责检验实例的存在性并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。

    • 单例类的构造函数为私有;
    • 提供一个自身的静态私有成员变量;
    • 提供一个公有的静态工厂方法。

    确保只有一个对象被实例化的关键在于将构造器私有化,这样外部无法使用new构建对象,也无法通过反射实例化对象,这样一种设计思想确保系统中只有一个实例,提供关键服务,但对于该实例来说内部封装的对象的操作在并发环境下仍要保持原子性,单例模式确保我只有我一个,最常用的便是提供序列化id,系统必须确保每次提供的是唯一id,因此采用单例模式+原子操作(静态方法+原子操作也可以)。

    public class Singleton {
    
        private static Singleton singleton=new Singleton();
    
        private static volatile long id;
        //单例模式,私有化构造器,避免其他类new该对象
        private Singleton(){
    
        }
        public static Singleton getSingleton() {
            return singleton;
        }
    
        public synchronized long getId(){
            return id++;
        }
    }
    
    public class SingletonPatternTest {
        public static void main(String[] args){
            //错误,不能访问私有
            //Singleton singleton=new Singleton();
            /*通过反射实例化将抛出java.lang.IllegalAccessException异常
            try {
                Singleton singleton=Singleton.class.newInstance();
            }catch (Exception e){
                e.printStackTrace();
            }
            */
            Singleton singleton=Singleton.getSingleton();
            for(int i=0;i<10;i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(Thread.currentThread().getName()+"我的id:"+singleton.getId());
                    }
                }).start();
            }
    
        }
    }
    
    展开全文
  • 设计模式之创建型模式

    千次阅读 2019-03-31 12:17:53
    设计模式之创建型模式:单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式、建造者模式

    一、简介

    创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能会导致设计上的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决问题。

    创建型模式(Creational Pattern)

    • 单例模式 Singleton Pattern: 单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
      使用频率:★★★★☆

    • 简单工厂模式 Simple Factory Pattern: 又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。
      使用频率:★★★☆☆

    • 工厂方法模式 Factory Method Pattern: 是一种常用的类创建型设计模式,此模式的核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。
      使用频率:★★★★★

    • 抽象工厂模式 Abstract Factory Pattern: 是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象。
      使用频率:★★★★★

    • 原型模式 Prototype Pattern: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
      使用频率:★★★☆☆

    • 建造者模式 Builder Pattern: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
      使用频率:★★☆☆☆

    二、单例模式

    2.1、饿汉式

    /**
     * 单例模式(饿汉式)
     * 线程安全,没有加锁,执行效率会提高。
     * 类加载时就初始化,浪费内存,容易产生垃圾对象
     * <p>
     * 单例类使用了final修饰,防止被继承
     * 这种写法比较简单,就是在类装载的时候就完成实例化。instance作为类变量,在类初始化过程中,会被收集进<clinit>()方法中,该方法会保障同步,从而避免了线程同步问题。
     * 在类装载的时候就完成实例化,若从未使用过这个实例,则会造成内存的浪费。
     */
    public final class SingleObject1 {
        //创建 SingleObject1 的一个对象
        private static SingleObject1 instance = new SingleObject1();
        //私有化构造函数,这样该类就不会被实例化
        private SingleObject1() {}
        //获取唯一可用的对象
        public static SingleObject1 getInstance() {
            return instance;
        }
        public void say() {
            System.out.println("Hello");
        }
    }
    
    ……
    //调用
    SingleObject1.getInstance().say();//Hello
    

    2.2、懒汉式,线程不安全

    /**
     * 单例模式(懒汉式,线程不安全)
     * 线程不安全,没有加锁。
     * 此方式在确定是单线程的情况下,可以保证创建的对象唯一性
     */
    public final class SingleObject2 {
        //创建 SingleObject1 的一个对象
        private static SingleObject2 instance;
        //私有化构造函数,这样该类就不会被实例化
        private SingleObject2() {}
        //获取唯一可用的对象
        public static SingleObject2 getInstance() {
            if (instance == null) {
                instance = new SingleObject2();
            }
            return instance;
        }
        public void say() {
            System.out.println("Hello");
        }
    }
    
    ……
    //调用
    SingleObject2.getInstance().say();//Hello
    

    2.3、懒汉式,线程安全

    /**
     * 单例模式(懒汉式,线程安全)
     * 线程安全,加锁,执行效率低
     */
    public final class SingleObject3 {
        //创建 SingleObject1 的一个对象
        private static SingleObject3 instance;
        //私有化构造函数,这样该类就不会被实例化
        private SingleObject3() {}
        //获取唯一可用的对象
        public synchronized static  SingleObject3 getInstance() {
            if (instance == null) {
                instance = new SingleObject3();
            }
            return instance;
        }
        public void say() {
            System.out.println("Hello");
        }
    }
    
    ……
    //调用
    SingleObject3.getInstance().say();//Hello
    

    2.4、双检锁/双重校验锁

    /**
     * 单例模式(双检锁/双重校验锁)
     * 线程安全
     * 种方式采用双锁机制,安全且在多线程情况下能保持高性能
     */
    public final class SingleObject4 {
        //创建 SingleObject1 的一个对象
        private volatile static SingleObject4 instance;
        //私有化构造函数,这样该类就不会被实例化
        private SingleObject4() {}
        //获取唯一可用的对象
        public static SingleObject4 getInstance() {
            if (instance == null) {
                synchronized (SingleObject4.class) {
                    if (instance == null) {
                        instance = new SingleObject4();
                    }
                }
            }
            return instance;
        }
        public void say() {
            System.out.println("Hello");
        }
    }
    
    ……
    //调用
    SingleObject4.getInstance().say();//Hello
    

    2.5、静态内部类方式

    /**
     * 单例模式(静态内部类实现模式)
     * 线程安全,调用效率高,可以延时加载
     * 这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。
     * 这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
     * 这种方式同样利用了 classloader 机制来保证初始化 instance 时只有一个线程,
     * <p>
     * 静态内部类方式是最好也是最常用的几种实现单例模式的方式之一
     */
    public final class SingleObject5 {
    
        private static class SingleObject5Holder {
            private static final SingleObject5 instance = new SingleObject5();
        }
        //私有化构造函数,这样该类就不会被实例化
        private SingleObject5() {}
        //获取唯一可用的对象
        public static SingleObject5 getInstance() {
            return SingleObject5Holder.instance;
        }
        public void say() {
            System.out.println("Hello");
        }
    }
    
    ……
    //调用单例
    SingleObject5.getInstance().say();//Hello
    

    2.6、枚举方式

    /**
     * 单例模式(枚举方式,Android不推荐)
     * 线程安全,调用效率高,不能延时加载,可以防止反射和反序列化调用
     * 这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。
     * 这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,
     * 防止反序列化重新创建新的对象,绝对防止多次实例化。不过,由于 JDK1.5 之后才加入 enum 特性,用这种方式写不免让人感觉生疏,在实际工作中,也很少用。
     * 不能通过 reflection attack 来调用私有构造方法。
     *
     * 枚举实现单例,不推荐在Android平台使用,因为内存消耗会其他方式多一些,Android官方也不推荐枚举,
     * Android平台推荐双重校验或者静态内部类单例,现在的Android开发环境jdk一般都大于1.5了。所以volatile的问题不必担心。
     * Java平台开发的Effective Java一书中推荐使用枚举实现单例,可以保证效率,而且还能解决反序列化创建新对象的问题。
     */
    public  enum SingleObject6 {
        INSTANCE;
    
        public void say() {
            System.out.println("Hello");
        }
    }
    
    ……
    //调用单例
    SingleObject6.INSTANCE.say();//Hello
    

    三、简单工厂模式

    3.1、定义接口

    定义人接口,吃的动作方法.

    public interface Human {
      	//吃动作
        void eat();
    }
    

    3.2、定义具体实现

    定义中国人.

    public class Chinese implements Human {
        @Override
        public void eat() {
            System.out.println("中国人吃饭");
        }
    }
    

    定义美国人.

    public class American implements Human {
        @Override
        public void eat() {
            System.out.println("美国人吃饭");
        }
    }
    

    3.3、定义工厂类

    方式一: 通过type创建工厂类

    public class HumanFactory {
        public static String CHINESE_HUMAN = "CHINESE_HUMAN";
        public static String AMERICAN_HUMAN = "AMERICAN_HUMAN";
    
        /**
         * 创建人类工厂方法
         * @param type {@link #CHINESE_HUMAN}、{@link #AMERICAN_HUMAN}
         * @return 人类
         */
        public Human createHuman(@NotNull String type) {
            if (type.equals(CHINESE_HUMAN)) {
                return new Chinese();
            } else if (type.equals(AMERICAN_HUMAN)) {
                return new American();
            }
            return null;
        }
    }
    

    方式二: 通过java反射方式创建工厂类

    public class HumanFactory2 {
        /**
         * 创建人类工厂方法
         * @param c 中国人、美国人
         * @param <T> 
         * @return 人类
         */
        public <T extends Human> T  createHuman(Class<T> c) {
            T t=null;
            try {
                t = (T) Class.forName(c.getName()).newInstance();
            } catch (InstantiationException e) {
                System.out.println("不支持抽象类或接口");
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                System.out.println("没有足够权限,即不能访问私有对象");
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                System.out.println("类不存在");
                e.printStackTrace();
            }
            return t;
        }
    }
    

    3.5、使用简单工厂模式

    public static void main(String[] args) {
        //----------------------方式一------------------------------
        //创建工厂类
        HumanFactory humanFactory=new HumanFactory();
        //创建美国人
        Human human1 = humanFactory.createHuman(HumanFactory.AMERICAN_HUMAN);
        human1.eat();//美国人吃饭
        //创建中国人
        Human human2 = humanFactory.createHuman(HumanFactory.CHINESE_HUMAN);
        human2.eat();//中国人吃饭
        
        //----------------------方式二------------------------------
         HumanFactory2 humanFactory2 = new HumanFactory2();
         Human human3 = humanFactory2.createHuman(American.class);
         human3.eat();//美国人吃饭
         Human human4 = humanFactory2.createHuman(Chinese.class);
         human4.eat();//中国人吃饭
    }
    

    四、工厂方法模式

    4.1、定义接口

    定义人接口,吃的动作方法.

    public interface Human {
      	//吃动作
        void eat();
    }
    

    定义工厂类接口

    //工厂接口类
    public interface Factory {
        //创建人类
        Human createHuman();
    }
    

    4.2、定义具体实现

    定义中国人.

    public class Chinese implements Human {
        @Override
        public void eat() {
            System.out.println("中国人吃饭");
        }
    }
    

    定义美国人.

    public class American implements Human {
        @Override
        public void eat() {
            System.out.println("美国人吃饭");
        }
    }
    

    定义中国人工厂类

    //中国人工厂类
    public class ChineseFactory implements Factory {
        @Override
        public Human createHuman() {
            return new Chinese();
        }
    }
    

    定义美国人工厂类

    //美国人工厂类
    public class AmericanFactory implements Factory{
        @Override
        public Human createHuman() {
            return new American();
        }
    }
    

    4.3、使用工厂方法模式

    public static void main(String[] args) {
        Factory factory1 = new AmericanFactory();
        Human human1 = factory1.createHuman();
        human1.eat();//美国人吃饭
    
        Factory factory2 = new ChineseFactory();
        Human human2 = factory2.createHuman();
        human2.eat();//中国人吃饭
    }
    

    五、抽象工厂模式

    5.1、定义接口

    定义人接口,吃的动作方法.

    public interface Human {
      	//吃动作
        void eat();
    }
    

    定义水果接口

    //水果接口
    public interface Fruits {
        //水果名称
        String name();
    }
    
    

    定义工厂接口,每个工厂都有制造人和苹果方法

    //工厂接口
    public interface Factory {
        //创建人类
        Human createHuman();
        //创建水果
        Fruits createFruits();
    }
    

    5.2、定义具体实现

    定义中国人

    public class Chinese implements Human {
        @Override
        public void eat() {
            System.out.println("中国人吃饭");
        }
    }
    

    定义美国人

    public class American implements Human {
        @Override
        public void eat() {
            System.out.println("美国人吃饭");
        }
    }
    

    定义苹果

    //苹果实体
    public class Apple implements Fruits{
        @Override
        public String name() {
            System.out.println("苹果");
            return "苹果";
        }
    }
    

    定义葡萄

    //葡萄实体
    public class Grape implements Fruits {
        @Override
        public String name() {
            System.out.println("葡萄");
            return "葡萄";
        }
    }
    

    定义制造中国人和苹果的工厂

    //制造工厂A 制造中国人和苹果
    public class CreateFactoryA  implements Factory{
        @Override
        public Human createHuman() {
            return new Chinese();
        }
        @Override
        public Fruits createFruits() {
            return new Apple();
        }
    }
    

    定义制造美国人和葡萄的工厂

    //制造工厂B 制造美国人和葡萄
    public class CreateFactoryB implements Factory{
        @Override
        public Human createHuman() {
            return new American();
        }
        @Override
        public Fruits createFruits() {
            return new Grape();
        }
    }
    
    

    5.3、使用抽象工厂模式

      public static void main(String[] args) {
            Factory factory1=new CreateFactoryA();
            Human human = factory1.createHuman();
            Fruits fruits = factory1.createFruits();
            human.eat();//中国人吃饭
            fruits.name();//苹果
    
            Factory factory2=new CreateFactoryB();
            Human human2 = factory2.createHuman();
            Fruits fruits2 = factory2.createFruits();
            human2.eat();//美国人吃饭
            fruits2.name();//葡萄
        }
    

    六、原型模式

    原型模式是一个创建型的模式。原型二字表明了改模式应该有一个样板实例,用户从这个样板对象中复制一个内部属性一致的对象,这个过程也就是我们称的“克隆”。被复制的实例就是我们所称的“原型”,这个原型是可定制的。原型模式多用于创建复杂的或者构造耗时的实例,因为这种情况下,复制一个已经存在的实例可使程序运行更高效。

    6.1、浅拷贝实现原型模式

    新建Book类实现Cloneable接口,复写clone方法

    //书原型(浅拷贝)
    public class Book implements Cloneable {
        //书名
        private String title;
        //书页数
        private ArrayList<String> page = new ArrayList<String>();
    
        public Book() {
            //一个实现了Cloneable并重写了clone方法的类,通过clone得到对象构造函数是不会被执行
            System.out.println("构造函数被执行了");
        }
    
        @Override
        protected Book clone() {
            try {
                return (Book) super.clone();
            } catch (CloneNotSupportedException e) {
                //异常处理
                e.printStackTrace();
                return null;
            }
        }
    
        public String getTitle() {return title;}
    
        public void setTitle(String title) {this.title = title;}
    
        public List<String> getPage() {return page;}
    
        public void addPage(String page) {this.page.add(page);}
    
        @Override
        public String toString() {
            return "Book{" +"title='" + title + '\'' +", page=" + page +'}';
        }
    }
    

    测试原型模式

    //浅拷贝测试
    Book book = new Book();
    book.setTitle("Java");
    book.addPage("Java第1章");
    System.out.println(book.toString());//Book{title='Java', page=[Java第1章]}
    
    Book cloneBook = book.clone();
    cloneBook.setTitle("Android");
    cloneBook.addPage("Android第1章");
    System.out.println(cloneBook.toString());//Book{title='Android', page=[Java第1章, Android第1章]}
    
    // 再次打印原始书本发现原书信息被修改(因为Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、集合、容器对象、引用对象等都不会拷贝,需要使用深拷贝解决)
    System.out.println(book.toString());//Book{title='Java', page=[Java第1章, Android第1章]}
    

    6.2、深拷贝实现原型模式

    新建Book类实现Cloneable接口,复写clone方法,因为Object类的clone方法只会拷贝对象中的基本的数据类型,对于数组、集合、容器对象、引用对象等都不会拷贝,需要将page进行深度拷贝.

    //书原型(深拷贝)
    public class Book2 implements Cloneable {
        //书名
        private String title;
        //书页数
        private ArrayList<String> page = new ArrayList<String>();
    
        @Override
        protected Book2 clone() {
            try {
                Book2 book2 = (Book2) super.clone();
                book2.page= (ArrayList<String>) this.page.clone();
                return book2;
            } catch (CloneNotSupportedException e) {
                //异常处理
                e.printStackTrace();
                return null;
            }
        }
    
        public String getTitle() {return title;}
    
        public void setTitle(String title) {this.title = title;}
    
        public List<String> getPage() {return page;}
    
        public void addPage(String page) {this.page.add(page);}
    
        @Override
        public String toString() {
            return "Book{" +"title='" + title + '\'' +", page=" + page +'}';
        }
    }
    

    测试原型模式

    //深拷贝测试
    Book2 book2 = new Book2();
    book2.setTitle("Java");
    book2.addPage("Java第1章");
    System.out.println(book2.toString());//Book{title='Java', page=[Java第1章]}
    
    Book2 cloneBook2 = book2.clone();
    cloneBook2.setTitle("Android");
    cloneBook2.addPage("Android第1章");
    System.out.println(cloneBook2.toString());//Book{title='Android', page=[Java第1章, Android第1章]}
    
    // 再次打印原始书本发现原书没有被改变
    System.out.println(book2.toString());//Book{title='Java', page=[Java第1章]}
    

    6.3、使用原型模式注意事项

    • 构造函数不会被执行

      通过clone复制得到对象,该对象构造函数是不会被执行的。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不 会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效。在单例模式中,只要将构造方法的访问权限设置为 private型,就可以实现单例。但是clone方法直接无视构造方法的权限,所以,单例模式与原型模式是冲突的。

    • 浅拷贝和深拷贝

      clone方法只会拷贝对象中的基本的数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝。在开发中,为减少错误,建议在使用原型模式时尽量使用深拷贝,避免操作副本时影响原始对象的问题。如果是在涉及类的继承时,父类有多个引用的情况就非常复杂,建议的方案是深拷贝和浅拷贝分开实现。

    • clone与final

      要使用clone方法,类的成员变量上不要增加final关键字,因为final类型是不允许重赋值的。

    七、建造者模式

    建造者模式是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

    7.1、建造者模式的定义

    定义产品类

    //具体产品类
    public class Product {
        private String name;
        private String desc;
        public String getName() {return name;}
        public void setName(String name) {this.name = name;}
        public String getDesc() {return desc;}
        public void setDesc(String desc) {this.desc = desc;}
        @Override
        public String toString() {
            return "Product{" +"name='" + name + '\'' +", desc='" + desc + '\'' +'}';
        }
    }
    

    定义抽象建造者

    //定义抽象建造者
    public abstract class Builder {
        //设置产品名称
        abstract void setName(String name);
        //设置产品描述
        abstract void setDesc(String desc);
        //构建产品
        abstract Product builderProduct();
    }
    

    定义具体建造者

    //定义具体建造者
    public class ConcreteProduct extends Builder {
        private final Product product;
        public ConcreteProduct() { product = new Product();}
        @Override
        void setName(String name) {
            product.setName(name);
        }
        @Override
        void setDesc(String desc) {
            product.setDesc(desc);
        }
        @Override
        Product builderProduct() {
            return product;
        }
    }
    

    定义指挥者类

    //定义指挥者类
    public class Director {
        private final ConcreteProduct concreteProduct;
        public Director() {
            concreteProduct = new ConcreteProduct();
        }
        public Product getProduct(String name,String desc){
            concreteProduct.setName(name);
            concreteProduct.setDesc(desc);
           return concreteProduct.builderProduct();
        }
    }
    

    使用建造者模式

    public static void main(String[] args) {
            Director director = new Director();
            Product product = director.getProduct("产品A", "A 的描述");
            System.out.println(product);//Product{name='产品A', desc='A 的描述'}
        }
    

    7.2、Android中建造者实现

    Android中的AlertDialog.Builder就是使用了Builder模式来构建AlertDialog的。

    Android AlertDialog简单构建与使用

    AlertDialog.Builder builder = new AlertDialog.Builder(activity);//创建一个Builder对象
      builder.setIcon(R.drawable.icon);
      builder.setTitle("标题");
      builder.setMessage("内容");
      builder.setPositiveButton("确定", null);
      AlertDialog alertDialog = builder.create();//创建AlertDialog对象
      alertDialog.show();//显示AlertDialog
    

    通过Builder对象来构建Icon、Title、Message、按钮监听等,将AlertDialog的构建过程和细节隐藏了起来。

    AlertDialog部分源码:

    public class AlertDialog extends AppCompatDialog implements DialogInterface {
        final AlertController mAlert;
        protected AlertDialog(@NonNull Context context) {
            this(context, 0);
        }
        ……
        public static class Builder {
            private final AlertController.AlertParams P;//存放构建时设置的参数
            ……
            public Builder(@NonNull Context context) {
                this(context, resolveDialogTheme(context, 0));
            }
    		……
         	public Builder(@NonNull Context context) {//构建Builder
                this(context, resolveDialogTheme(context, 0));
            }
            ……
            public Builder setTitle(@Nullable CharSequence title) {//设置标题
                P.mTitle = title;
                return this;
            }
            ……
            public Builder setMessage(@Nullable CharSequence message) {//设置内容
                P.mMessage = message;
                return this;
            }
    		……
            public Builder setIcon(@DrawableRes int iconId) {//设置icon
                P.mIconId = iconId;
                return this;
            }
    		……
            public Builder setPositiveButton(CharSequence text, final OnClickListener listener) {//设置按钮和监听
                P.mPositiveButtonText = text;
                P.mPositiveButtonListener = listener;
                return this;
            }
    		……
            public AlertDialog create() {//构建AlertDialog
                final AlertDialog dialog = new AlertDialog(P.mContext, mTheme);
                P.apply(dialog.mAlert);//将构建时参数通过AlertController运用到AlertDialog上
                dialog.setCancelable(P.mCancelable);
                if (P.mCancelable) {dialog.setCanceledOnTouchOutside(true);}
                dialog.setOnCancelListener(P.mOnCancelListener);
                dialog.setOnDismissListener(P.mOnDismissListener);
                if (P.mOnKeyListener != null) {dialog.setOnKeyListener(P.mOnKeyListener);}
                return dialog;
            }
    		……
        }
    }
    

    AlertController部分源码:

    class AlertController { 
    	public static class AlertParams {
      	……
            public void apply(AlertController dialog) {//将构建时参数通过AlertController运用到AlertDialog上
                if (mCustomTitleView != null) {
                    dialog.setCustomTitle(mCustomTitleView);
                } else {
                    if (mTitle != null) {
                        dialog.setTitle(mTitle);
                    }
                    if (mIcon != null) {
                        dialog.setIcon(mIcon);
                    }
                    if (mIconId != 0) {
                        dialog.setIcon(mIconId);
                    }
                    if (mIconAttrId != 0) {
                        dialog.setIcon(dialog.getIconAttributeResId(mIconAttrId));
                    }
                }
                if (mMessage != null) {
                    dialog.setMessage(mMessage);
                }
                if (mPositiveButtonText != null || mPositiveButtonIcon != null) {
                    dialog.setButton(DialogInterface.BUTTON_POSITIVE, mPositiveButtonText,
                            mPositiveButtonListener, null, mPositiveButtonIcon);
                }
                ……
    

    Android中 AlertDialog使用是通过AlertDialog.Builder设置各种属性后(如:setTitle()),这些属性信息会保存在P(AlertController.AlertParams)变量中,调用create()即可返回一个AlertDialog对象,create()方法中P.apply(dialog.mAlert)是将构建时设置的参数通过AlertController运用到AlertDialog上,最后调用AlertDialog中的show()显示对话框。AlertDialog通过builder模式隐藏了这种复杂的构建过程,只需几行简单的代码就把AlertDialog给展示出来了,AlertDialogbuilder中并没有抽象建造者(Builder)、Director(指挥者类)等角色。AlertDialog.Builder同时扮演了BuilderConcreteBuilderDirector等角色,这是Android源码中使用构建者模式的一种简化。

    展开全文
  • 分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!...本文主要介绍依赖注入原理和常见的实现方式,重点在于介绍这种年轻的设计模式的适用场景及优势...
  • 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高...
  • 设计模式-创建型模式总结

    千次阅读 2017-07-24 20:24:25
    创建型模式,顾名思义,就是用来创建对象的模式。它抽象了实例化过程,帮助一个系统独立于如何创建、组合和表示它的对象。
  • 创建型模式——单例模式

    千次阅读 2020-07-09 10:19:51
    单例模式是最简单的设计模式之一,属于创建型模式,它提供了一种特殊的创建对象的方式,确保全局中只有单个对象被创建。这个设计模式主要目的是想在整个系统中只能出现类的一个实例,即一个类只有一个对象。 单例...
  • 好吧,在Java 5之前的版本,使用双重检查锁定创建单例Singleton,记得使用volatile变量。从Java 5开始,使用Enum创建线程安全的Singleton很容易。 Java枚举和单例模式 Java中的枚举单例模式是使用枚举在Jav...
  • 创建型模式——建造者模式

    千次阅读 2020-07-21 11:16:33
    建造者模式,又被称为生成器模式,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。使用多个简单的对象一步一步构建成一个复杂的对象,有点像造房子一样一步步从地基做起到万丈高楼。 将一个...
  • 创建型模式——工厂方法模式

    千次阅读 2020-07-10 08:22:13
    创建型模式——工厂方法模式 (一)概述 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method是一个类的实例化延迟到其子类。 在工厂方法模式中,核心的工厂类不再负责所有的产品的...
  • 创建型模式

    千次阅读 热门讨论 2013-01-08 10:21:52
    创建型模式表现的是对象的创建过程和用户所使用的对象之间的关系。   创建模式包括: 工厂方法模式 抽象工厂模式 原型模式 单例模式 创建者模式    本篇文章主要介绍单例模式和创建者模式,前面几篇文章...
  • 设计模式 ① — 创建型模式

    千次阅读 2018-06-07 11:24:26
    创建型模式: 负责对象的创建。工厂方法模式(Factory Method);解决某个对象的创建工作。抽象工厂模式(Abstract Factory): 解决一系列相互依赖对象的创建工作。创建者模式(Builder):解决“一些复杂对象”的...
  • 设计模式--创建型模式-单例模式

    万次阅读 2021-02-01 18:10:29
    单例模式是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。 问题 单例模式同时解决了两个问题, 所以违反了_单一职责原则_: 1. 保证一个类只有一个实例。 2. 为该实例...
  • 所有的创建型模式都是用作解决对象的创建或实例化问题的解决方案。 1  简单工厂模式 创建对象的最简单方法是使用new来创建一个对象,如果只创建一种固定不变的对象,可以使用new来创建这个对象。 如果要根据不同...
  • 设计模式之“创建型模式

    千次阅读 热门讨论 2014-12-08 12:02:53
    创建型模式主要分为五大模式,分别为:抽象工厂模式、建造者模式、工厂方法模式、原型模式、单例模式。 抽象工厂模式  提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 一、优点...
  • 引用《软件秘笈-设计模式那点事》书籍: 按照目的来分,设计模式可以分为创建型模式、...创建型模式用来处理对象的创建过程,主要包含以下5种设计模式:  工厂方法模式(Factory Method Pattern)  抽象工
  • 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。是一种能快速创建相似对象的模式。在软件开发中应用较为广泛。 原型模式优缺点 优点: 1、 当创建新的对象实例较为复杂时,使用原型模式可以...
  • 创建型模式中关于工厂的模式

    千次阅读 热门讨论 2014-03-21 11:09:41
    创建型模式中,有3中关于工厂的模式,分别是:简单工厂模式,工厂方法模式,抽象工厂模式。这3中模式既有各自的优点,同时,这3中模式又可以逐步演化:如,简单工厂可以演化成工厂方法,工厂方法可以演化成抽象...
  • 创建型模式--工厂方法模式

    千次阅读 2014-12-21 10:56:57
    定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。  适用性 1.当一个类不知道它所必须创建的对象的类的时候。 2.当一个类希望由它的子类来指定它所...
  • 设计模式汇总:创建型模式

    万次阅读 2016-04-30 17:26:47
    创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 行为型模式,共十一种:...
  • 【大话设计模式】--创建型模式总结

    千次阅读 热门讨论 2015-01-06 16:15:18
    在软件工程中,创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对 象创建方式可能会导致设计时间的问题,或增加设计的复杂度。创建型模式通过以某种方式控制对象的创建来解决...
  • 创建型模式总结

    千次阅读 热门讨论 2019-03-21 17:41:12
    创建型模式有以下几个模式: 简单工厂:用来生产同一等级结构中的任意产品。(不支持拓展增加产品) 工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品) 抽象工厂 :用来生产不同产品族的全部...
  • 设计模式--六种创建型模式

    千次阅读 热门讨论 2017-04-13 16:58:25
    前言  每几种模式之间都有一定的联系,从中发现它们的相同点和不同点,研究发生改变的节点,这就是本篇博客所要说明的创建型设计模式之间的联系。它们包括:简单工厂模式、...一个类创建型模式使用继承改变被实例
  • 前言    每几种模式之间都有一定的联系,从中发现它们的相同点和不同点,研究发生改变的节点,这就是本篇博客所要说明的创建型设计模式之间的联系。...一个类创建型模式使用继承改变被实例化的类...
  • 创建型设计模式之Builder模式

    千次阅读 2017-04-30 11:28:05
     Builder模式是一步一步创建一个复杂对象创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程。该模式是为了将构建复杂对象的过程和它的部件解耦,使得构建过程和部件的表示...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 242,979
精华内容 97,191
关键字:

创建型模式主要用于创建对象