……

一、什么是设计模式                                                                                                                                       

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。简单说:

模式:在某些场景下,针对某类问题的某种通用的解决方案。

场景:项目所在的环境

问题:约束条件,项目目标等

解决方案:通用、可复用的设计,解决约束达到目标。

二、各分类中模式的关键点                                                                                                                             

单例模式:某个类只能有一个实例,提供一个全局的访问点。

简单工厂:一个工厂类根据传入的参量决定创建出那一种产品类的实例。

工厂方法:定义一个创建对象的接口,让子类决定实例化那个类。

抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类。

建造者模式:封装一个复杂对象的构建过程,并可以按步骤构造。

原型模式:通过复制现有的实例来创建新的实例。

 

适配器模式:将一个类的方法接口转换成客户希望的另外一个接口。

组合模式:将对象组合成树形结构以表示“”部分-整体“”的层次结构。

装饰模式:动态的给对象添加新的功能。

代理模式:为其他对象提供一个代理以便控制这个对象的访问。

亨元(蝇量)模式:通过共享技术来有效的支持大量细粒度的对象。

外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。

桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。

 

模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。

解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。

策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。

状态模式:允许一个对象在其对象内部状态改变时改变它的行为。

观察者模式:对象间的一对多的依赖关系。

备忘录模式:在不破坏封装的前提下,保持对象的内部状态。

中介者模式:用一个中介对象来封装一系列的对象交互。

命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。

访问者模式:在不改变数据结构的前提下,增加作用于一组对象元素的新功能。

责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。

迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。

三、设计模式六大原则

1.开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行扩展的时候,不能去修改原有代码,实现一个热插拔的效果。
所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后面的具体设计中我们会体会到这点

2.里氏代换原则(Liskov Substitution Principle)LSP
面向对象设计的基本原则之一。里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。
LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。
里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。
而基类与子类的继承关系就是抽象化的具体体现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

3.依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。

4.接口隔离原则(Interface Segregation Principle)

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这个我们看出,其实设计模式就是一个软件的设计思想从大型软件架构出发,为了升级和维护方便,要降低依赖,降低耦合

5.迪米特法则(最少知道原则)(Demeter Principle)
为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立

6.合成复用原则(Composite Reuse Principle)
原则是尽量使用合成、聚合的方式,而不是使用继承。

四、设计模式的三个分类                                                                                                                                

创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。

结构型模式:把类或对象结合在一起形成一个更大的结构。

行为型模式:类和对象如何交互,及划分责任和算法。

如下图所示:

 

1、创建式模式之单例模式

单例模式,它的定义就是确保某一个类只有一个实例,并且提供一个全局访问点。

1、单例模式有 3 个特点:
  1. 单例类只有一个实例对象;
  2. 该单例对象必须由单例类自行创建;
  3. 单例类对外提供一个访问该单例的全局访问点。
2、单例模式优缺点
①、单例模式的优点:
  • 单例模式可以保证内存里只有一个实例,减少了内存的开销。
  • 可以避免对资源的多重占用。
  • 单例模式设置全局访问点,可以优化和共享资源的访问。
②、单例模式的缺点:
    • 单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则。
    • 在并发测试中,单例模式不利于代码调试。在调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。
    • 单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。
3、单例模式的应用场景

单例模式的主要角色如下。

  • 单例类:包含一个实例且能自行创建这个实例的类。
  • 访问类:使用单例的类。

 

 

 

对于 java 来说,单例模式可以保证在一个 JVM 中只存在单一实例。单例模式的应用场景主要有以下几个方面。
    • 需要频繁创建的一些类,使用单例可以降低系统的内存压力,减少 GC。
    • 某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号等。
    • 某些类创建实例时占用资源较多,或实例化耗时较长,且经常使用。
    • 某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。
    • 频繁访问数据库或文件的对象。
    • 对于一些控制硬件级别的操作,或者从系统上来讲应当是单一控制逻辑的操作,如果有多个实例,则系统会完全乱套。
    • 当对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。

 因此当系统中只需要一个实例对象或者系统中只允许一个公共访问点,除了这个公共访问点外,不能通过其他访问点访问该实例时,可以使用单例模式。

单例模式的主要优点就是节约系统资源、提高了系统效率,同时也能够严格控制客户对它的访问。也许就是因为系统中只有一个实例,这样就导致了单例类的职责过重,违背了“单一职责原则”,同时也没有抽象类,所以扩展起来有一定的困难。其UML结构图非常简单,就只有一个类,如下图:

4、懒汉和饿汉的异同点

区别1:懒汉的特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例,相当于饭来张口。但饿汉式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。

区别2:懒汉式如果编写的是多线程程序,则不要删除上例代码中的关键字 volatile 和 synchronized,否则将存在线程非安全的问题。如果不删除这两个关键字就能保证线程安全,但是每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。但饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题。

相同点:属性类型和方法返回类型都是自身本类,且构造方法和方法都无参型。

5、饿汉式实现选举总统
package DesignModel.CreatedModel.Singleton;

/**
 * @program: FlinkUdf
 * @description: 懒汉式模式
 * 特点:
 * 1、属性类型和方法返回类型都是本类
 * 2、构造方法和方法都是无参型
 * @author: BigData
 * @create: 2020-11-27 16:14
 **/
public class LazySingleton {
    private  static volatile LazySingleton instance=null;
    private LazySingleton() {
        System.out.println("产生一个总统!");
    }
    public static  synchronized LazySingleton getInstance()
    {
        if(instance==null)
        {
            instance=new LazySingleton();
        }
        else
        {
            System.out.println("已经有一个总统,不能产生新总统!");
        }
        return instance;
    }
    public void getName()
    {
        System.out.println("我是美国总统:特朗普。");
    }
}
6、饿汉式实现猪八戒
package DesignModel.CreatedModel.Singleton;

import javax.swing.*;
import java.awt.*;

/**
 * @program: FlinkUdf
 * @description: 饿汉式单例模式
 * 特点:
 * 1、与懒汉式不同之处是饿汉式先实例化本类,抢着进食
 * 2、与懒汉式相同之处是属性类型和方法返回类型都是本类,且方法和构造方法都是无参型
 * @author: BigData
 * @create: 2020-11-27 16:29
 **/
public class HungrySingleton extends JPanel {
    public static final HungrySingleton instance=new HungrySingleton();
    public HungrySingleton() {
        JPanel jPanel=new JPanel();
        JLabel label = new JLabel();
        ImageIcon imageIcon = new ImageIcon("C:\\app\\FlinkUdf\\src\\Img\\Bajie.jpg");
        label.setIcon(imageIcon);
        jPanel.add(label);
        add(jPanel);
    }
    public static HungrySingleton getInstance()
    {
        return  instance;
    }
}
7、懒汉和饿汉实现测试
package DesignModel.CreatedModel.Singleton;
import javax.swing.*;
import java.awt.*;
/**
 * @program: FlinkUdf
 * @description: 单例模式实现
 * @author: BigData
 * @create: 2020-11-27 16:36
 **/
public class SingletonImp {
    public static void main(String[] args) {
        /**
         * 1、懒汉式实现
         */
        LazySingleton lazySingleton=LazySingleton.getInstance();
        lazySingleton.getName();
        LazySingleton lazySingleton1=LazySingleton.getInstance();
        lazySingleton1.getName();
        if(lazySingleton==lazySingleton1)
        {
            System.out.println("他们是同一个人");
        }
        else
        {
            System.out.println("他们不是同一个人");
        }
        /**
         * 2、饿汉式实现
         */
        JFrame jf=new JFrame("饿汉单例模式测试");
        jf.setLayout(new GridLayout(1,2));
        Container contentPane=jf.getContentPane();
        HungrySingleton hungrySingleton=HungrySingleton.getInstance();
        contentPane.add(hungrySingleton);
        HungrySingleton hungrySingleton1=HungrySingleton.getInstance();
        contentPane.add(hungrySingleton1);
        if(hungrySingleton==hungrySingleton1)
        {
            System.out.println("他们是同一人!");
        }
        else
        {
            System.out.println("他们不是同一人!");
        }
        jf.pack();
        jf.setVisible(true);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }
}

结果:

"C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=52689:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\defaultuser0\AppData\Local\Temp\classpath541520150.jar DesignModel.CreatedModel.Singleton.SingletonImp
产生一个总统!
我是美国总统:特朗普。
已经有一个总统,不能产生新总统!
我是美国总统:特朗普。
他们是同一个人
他们是同一人!

2.创建式模式之工厂方法模式 

工厂模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。按实际业务场景划分,工厂模式有 3 种不同的实现方式,分别是简单工厂模式、工厂方法模式和抽象工厂模式。我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。                                                                                                                                   

作为抽象工厂模式的孪生兄弟,工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,也就是说工厂方法模式让实例化推迟到子类。

工厂方法模式非常符合“开闭原则”,当需要增加一个新的产品时,我们只需要增加一个具体的产品类和与之对应的具体工厂即可,无须修改原有系统。同时在工厂方法模式中用户只需要知道生产产品的具体工厂即可,无须关系产品的创建过程,甚至连具体的产品类名称都不需要知道。虽然他很好的符合了“开闭原则”,但是由于每新增一个新产品时就需要增加两个类,这样势必会导致系统的复杂度增加。其UML结构图:

 1、工厂方法模式 的优缺点
①、优点:
  • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
  • 灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。
  • 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
②、缺点:
  • 类的个数容易过多,增加复杂度
  • 增加了系统的抽象性和理解难度
  • 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。
2、工厂方法模式的应用场景
  • 客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
  • 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
  • 客户不关心创建产品的细节,只关心产品的品牌
3、工厂方法模式的模式结构

工厂方法模式的主要角色如下。

  1. 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
  2. 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  3. 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
  4. 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。


其结构图如图 1 所示。

 

 

4、 模式的应用示例

【例1】用工厂方法模式设计畜牧场。

分析:有很多种类的畜牧场,如养马场用于养马,养牛场用于养牛,所以该实例用工厂方法模式比较适合。

对养马场和养牛场等具体工厂类,只要定义一个生成动物的方法 newAnimal() 即可。由于要显示马类和牛类等具体产品类的图像,所以它们的构造函数中用到了 JPanel、JLabd 和 ImageIcon 等组件,并定义一个 show() 方法来显示它们。

客户端程序通过对象生成器类 ReadXML2 读取 XML 配置文件中的数据来决定养马还是养牛。其结构图如图 2 所示。

 

 

1、抽象动物工厂
package DesignModel.CreatedModel.FactoryMethod;

/**
 * @program: FlinkUdf
 * @description: 抽象产品:动物类
 * @author: BigData
 * @create: 2020-11-30 10:50
 **/
public interface Animal {
    public void show();
}
2、具体马产品类
package DesignModel.CreatedModel.FactoryMethod;

import javax.swing.*;
import java.awt.*;

/**
 * @program: FlinkUdf
 * @description: 实现动物工厂的具体产品马类
 * @author: BigData
 * @create: 2020-11-30 10:53
 **/
public class Horse implements Animal {
    JScrollPane sp;
    JFrame jf = new JFrame("工厂方法模式测试");
    public Horse()
    {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("动物:马"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("C:\\app\\FlinkUdf\\src\\Img/A_Horse.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //用户点击窗口关闭
    }
    @Override
    public void show() {
        jf.setVisible(true);
    }
}
3、具体牛产品类
package DesignModel.CreatedModel.FactoryMethod;

import javax.swing.*;
import java.awt.*;

/**
 * @program: FlinkUdf
 * @description: 实现动物工厂的具体产品牛类
 * @author: BigData
 * @create: 2020-11-30 10:53
 **/
public class Cattle implements Animal {
    JScrollPane sp;
    JFrame jf = new JFrame("工厂方法模式测试");
    public Cattle()
    {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("动物:马"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("C:\\app\\FlinkUdf\\src\\Img/A_Cattle.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //用户点击窗口关闭
    }
    @Override
    public void show() {

        jf.setVisible(true);
    }
}
4、抽象畜牧厂
package DesignModel.CreatedModel.FactoryMethod;
//抽象工厂:畜牧场
public interface AnimalFarm {
    public Animal newAnimal();
}
5、马畜牧厂产品实现类
package DesignModel.CreatedModel.FactoryMethod;

/**
 * @program: FlinkUdf
 * @description: 马畜牧厂产品实现类
 * @author: BigData
 * @create: 2020-11-30 11:21
 **/
public class HorseFarm implements AnimalFarm {

    @Override
    public Animal newAnimal() {
        System.out.println("新马出生!");
        return new Horse();
    }
}
6、牛畜牧厂产品实现类
package DesignModel.CreatedModel.FactoryMethod;

/**
 * @program: FlinkUdf
 * @description: 牛畜牧厂产品实现类
 * @author: BigData
 * @create: 2020-11-30 11:21
 **/
public class CattleFarm implements AnimalFarm {

    @Override
    public Animal newAnimal() {
        System.out.println("新牛出生!");
        return new Cattle();
    }
}
7、测试实现类
package DesignModel.CreatedModel.FactoryMethod;

/**
 * @program: FlinkUdf
 * @description: 畜牧厂实现测试类
 * @author: BigData
 * @create: 2020-11-30 11:26
 **/
public class AnimalFarmTest {
    public static void main(String[] args) {
       try {
           Animal animal;
           AnimalFarm animalFarm;
           animalFarm= (AnimalFarm) ReadXML2.getObject();
           animal=animalFarm.newAnimal();
           animal.show();
       }
       catch (Exception e)
       {
           System.out.println(e.getMessage());
       }
    }
}

结果:

"C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=51333:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\defaultuser0\AppData\Local\Temp\classpath702159594.jar DesignModel.CreatedModel.FactoryMethod.AnimalFarmTest
新类名:DesignModel.CreatedModel.FactoryMethod.HorseFarm
新马出生!

 

 

8、工具类之读取xml文件
package DesignModel.CreatedModel.FactoryMethod;

import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;

import java.io.*;

/**
 * @program: FlinkUdf
 * @description: 读取XMl文件类
 * @author: BigData
 * @create: 2020-11-30 11:30
 **/
public class ReadXML2 {
    public static Object getObject(String className) {
        try {
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse("C:\\app\\FlinkUdf\\src\\Img/config2.xml");
            NodeList nl = doc.getElementsByTagName(className);
            Node classNode = nl.item(0).getFirstChild();
            String cName = "DesignModel.CreatedModel.FactoryMethod." + classNode.getNodeValue();
            System.out.println("新类名:" + cName);
            Class<?> c = Class.forName(cName);
            Object obj = c.newInstance();
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
 9、整合汇总
package DesignModel.CreatedModel.FactoryMethod;
import javax.swing.*;
import java.awt.*;

/**
 * @program: FlinkUdf
 * @description: 动物工厂测试
 * @author: BigData
 * @create: 2020-11-30 16:41
 **/
public class AnimalFarmTest {
    public static void main(String[] args) {
        try {
            Animal animal;
            AnimalFarm farm;
            farm= (AnimalFarm) ReadXML2.getObject("className");
            animal=farm.newAnimal();
            animal.show();
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}
//抽象产品:动物类
interface Animal {
    public void show();
}

//具体产品:马类
class Horse implements Animal {
    JScrollPane sp;
    JFrame jf = new JFrame("工厂方法模式测试");

    public Horse() {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("动物:马"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("src/Img/A_Horse.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //用户点击窗口关闭
    }

    public void show() {
        jf.setVisible(true);
    }
}

//具体产品:牛类
class Cattle implements Animal {
    JScrollPane sp;
    JFrame jf = new JFrame("工厂方法模式测试");

    public Cattle() {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("动物:牛"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("src/Img/A_Cattle.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //用户点击窗口关闭
    }

    public void show() {
        jf.setVisible(true);
    }
}

//抽象工厂:畜牧场
interface AnimalFarm {
    public Animal newAnimal();
}

//具体工厂:养马场
class HorseFarm implements AnimalFarm {
    public Animal newAnimal() {
        System.out.println("新马出生!");
        return new Horse();
    }
}

//具体工厂:养牛场
class CattleFarm implements AnimalFarm {
    public Animal newAnimal() {
        System.out.println("新牛出生!");
        return new Cattle();
    }
}

3.创建式模式之抽象工厂模式 

同种类称为同等级,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。                                                                                                                        

所谓抽象工厂模式就是提供一个接口,用于创建相关或者依赖对象的家族,而不需要明确指定具体类。他允许客户端使用抽象的接口来创建一组相关的产品,而不需要关系实际产出的具体产品是什么。这样一来,客户就可以从具体的产品中被解耦。它的优点是隔离了具体类的生成,使得客户端不需要知道什么被创建了,而缺点就在于新增新的行为会比较麻烦,因为当添加一个新的产品对象时,需要更加需要更改接口及其下所有子类。其UML结构图如下:

 

 将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,图 1 所示的是海尔工厂和 TCL 工厂所生产的电视机与空调对应的关系图。

 

 

 

1、模式的定义与特点

抽象工厂(AbstractFactory)模式的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。

抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。

使用抽象工厂模式一般要满足以下条件。

  • 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
  • 系统一次只可能消费其中某一族产品,即同族的产品一起使用。


抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。

  • 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
  • 当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品组。
  • 抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则。


其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。增加了系统的抽象性和理解难度。

2、模式的结构与实现

抽象工厂模式同工厂方法模式一样,也是由抽象工厂、具体工厂、抽象产品和具体产品等 4 个要素构成,但抽象工厂中方法个数不同,抽象产品的个数也不同。现在我们来分析其基本结构和实现方法。

1. 模式的结构

抽象工厂模式的主要角色如下。

  1. 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
  2. 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
  3. 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
  4. 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。


抽象工厂模式的结构图如图 2 所示。

 

 

 

3、模式应用示例

【例1】用抽象工厂模式设计农场类。

分析:农场中除了像畜牧场一样可以养动物,还可以培养植物,如养马、养牛、种菜、种水果等,所以本实例比前面介绍的畜牧场类复杂,必须用抽象工厂模式来实现。

本例用抽象工厂模式来设计两个农场,一个是韶关农场用于养牛和种菜,一个是上饶农场用于养马和种水果,可以在以上两个农场中定义一个生成动物的方法 newAnimal() 和一个培养植物的方法 newPlant()。

 

 1、动物工厂
package DesignModel.CreatedModel.AbstractFactory;

/**
 * @program: FlinkUdf
 * @description: 抽象产品:动物类
 * @author: BigData
 * @create: 2020-11-30 10:50
 **/
public interface Animal {
    public void show();
}
2、马动物产品实现
package DesignModel.CreatedModel.AbstractFactory;

import javax.swing.*;
import java.awt.*;

/**
 * @program: FlinkUdf
 * @description: 实现动物工厂的具体产品马类
 * @author: BigData
 * @create: 2020-11-30 10:53
 **/
public class Horse implements Animal {
    JScrollPane sp;
    JFrame jf = new JFrame("抽象工厂模式测试");
    public Horse()
    {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("动物:马"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("C:\\app\\FlinkUdf\\src\\Img/A_Horse.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //用户点击窗口关闭
    }
    @Override
    public void show() {
        jf.setVisible(true);
    }
}
3、牛动物产品实现
package DesignModel.CreatedModel.AbstractFactory;

import javax.swing.*;
import java.awt.*;

/**
 * @program: FlinkUdf
 * @description: 实现动物工厂的具体产品牛类
 * @author: BigData
 * @create: 2020-11-30 10:53
 **/
public class Cattle implements Animal {
    JScrollPane sp;
    JFrame jf = new JFrame("抽象工厂模式测试");
    public Cattle()
    {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("动物:马"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("C:\\app\\FlinkUdf\\src\\Img/A_Cattle.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //用户点击窗口关闭
    }
    @Override
    public void show() {

        jf.setVisible(true);
    }
}
4、植物工厂
package DesignModel.CreatedModel.AbstractFactory;

/**
 * 抽象产品:植物类
 */
public interface Plant {
    public void show();
}
5、水果产品实现类
package DesignModel.CreatedModel.AbstractFactory;

import javax.swing.*;
import java.awt.*;

/**
 * @program: FlinkUdf
 * @description: 实现植物工厂的具体产品水果类
 * @author: BigData
 * @create: 2020-11-30 10:53
 **/
public class Fruitage implements Plant {
    JScrollPane sp;
    JFrame jf = new JFrame("抽象工厂模式测试");
    public Fruitage()
    {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("植物:香蕉"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("C:\\app\\FlinkUdf\\src\\Img/P_Fruitage.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //用户点击窗口关闭
    }
    @Override
    public void show() {
        jf.setVisible(true);
    }
}
6、蔬菜产品类实现
package DesignModel.CreatedModel.AbstractFactory;

import javax.swing.*;
import java.awt.*;

/**
 * @program: FlinkUdf
 * @description: 实现植物工厂的具体产品蔬菜类
 * @author: BigData
 * @create: 2020-11-30 10:53
 **/
public class Vegetables implements Plant {
    JScrollPane sp;
    JFrame jf = new JFrame("抽象工厂模式测试");
    public Vegetables()
    {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("植物:蔬菜"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("C:\\app\\FlinkUdf\\src\\Img/P_Vegetables.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    //用户点击窗口关闭
    }
    @Override
    public void show() {
        jf.setVisible(true);
    }
}
7、农场工厂
package DesignModel.CreatedModel.AbstractFactory;
//抽象工厂:农场类
public interface Farm {
public Animal newAnimal();
public Plant newPlant();
}
8、韶关农场类实现
package DesignModel.CreatedModel.AbstractFactory;

/**
 * @program: FlinkUdf
 * @description: 具体工厂:韶关农场类
 * @author: BigData
 * @create: 2020-11-30 15:58
 **/
public class SGfarm implements Farm {
    @Override
    public Animal newAnimal() {
        System.out.println("新马出生!!");
        return new Horse();
    }

    @Override
    public Plant newPlant() {
        System.out.println("水果长成!");
        return  new Fruitage();
    }
}
9、上饶农场类实现
package DesignModel.CreatedModel.AbstractFactory;

/**
 * @program: FlinkUdf
 * @description: 具体工厂:上饶农场类
 * @author: BigData
 * @create: 2020-11-30 16:03
 **/
public class SRfarm implements Farm {
    @Override
    public Animal newAnimal() {
        System.out.println("新牛出生!");
        return new Cattle();
    }

    @Override
    public Plant newPlant() {
        System.out.println("蔬菜长成!");
        return new Vegetables();
    }
}
10、农场测试类实现
package DesignModel.CreatedModel.AbstractFactory;

/**
 * @program: FlinkUdf
 * @description: 畜牧厂实现测试类
 * @author: BigData
 * @create: 2020-11-30 11:26
 **/
public class FarmTest {
    public static void main(String[] args) {
       try {
           Farm farm;
           Animal animal;
           Plant plant;
            farm = (Farm) ReadXML2.getObject("className");
            animal = farm.newAnimal();
            plant = farm.newPlant();
       }
       catch (Exception e)
       {
           System.out.println(e.getMessage());
       }
    }
}

11、汇总整合

package DesignModel.CreatedModel.AbstractFactory;

import javax.swing.*;
import java.awt.*;

/**
 * @program: FlinkUdf
 * @description: 工厂实现测试
 * @author: BigData
 * @create: 2020-11-30 16:33
 **/
//抽象产品:动物类
interface Animal {
    public void show();
}

//具体产品:马类
class Horse implements Animal {
    JScrollPane sp;
    JFrame jf = new JFrame("抽象工厂模式测试");

    public Horse() {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("动物:马"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("C:\\app\\FlinkUdf\\src\\Img/A_Horse.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭
    }

    public void show() {
        jf.setVisible(true);
    }
}

//具体产品:牛类
class Cattle implements Animal {
    JScrollPane sp;
    JFrame jf = new JFrame("抽象工厂模式测试");

    public Cattle() {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("动物:牛"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("C:\\app\\FlinkUdf\\src\\Img/A_Cattle.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭
    }

    public void show() {
        jf.setVisible(true);
    }
}

//抽象产品:植物类
interface Plant {
    public void show();
}

//具体产品:水果类
class Fruitage implements Plant {
    JScrollPane sp;
    JFrame jf = new JFrame("抽象工厂模式测试");

    public Fruitage() {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("植物:水果"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("C:\\app\\FlinkUdf\\src\\Img/P_Fruitage.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭
    }

    public void show() {
        jf.setVisible(true);
    }
}

//具体产品:蔬菜类
class Vegetables implements Plant {
    JScrollPane sp;
    JFrame jf = new JFrame("抽象工厂模式测试");

    public Vegetables() {
        Container contentPane = jf.getContentPane();
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(1, 1));
        p1.setBorder(BorderFactory.createTitledBorder("植物:蔬菜"));
        sp = new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1 = new JLabel(new ImageIcon("C:\\app\\FlinkUdf\\src\\Img/P_Vegetables.jpg"));
        p1.add(l1);
        jf.pack();
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭
    }

    public void show() {
        jf.setVisible(true);
    }
}

//抽象工厂:农场类
interface Farm {
    public Animal newAnimal();

    public Plant newPlant();
}

//具体工厂:韶关农场类
class SGfarm implements Farm {
    public Animal newAnimal() {
        System.out.println("新牛出生!");
        return new Cattle();
    }

    public Plant newPlant() {
        System.out.println("蔬菜长成!");
        return new Vegetables();
    }
}

//具体工厂:上饶农场类
class SRfarm implements Farm {
    public Animal newAnimal() {
        System.out.println("新马出生!");
        return new Horse();
    }

    public Plant newPlant() {
        System.out.println("水果长成!");
        return new Fruitage();
    }
}
public class FarmTest {
    public static void main(String[] args) {
        try {
            Farm f;
            Animal a;
            Plant p;
            f = (Farm) ReadXML2.getObject("className");
            a = f.newAnimal();
            p = f.newPlant();
            a.show();
            p.show();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

}

结果:

"C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=52677:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\defaultuser0\AppData\Local\Temp\classpath635323867.jar DesignModel.CreatedModel.AbstractFactory.FarmTest
新类名:DesignModel.CreatedModel.AbstractFactory.SGfarm
新牛出生!
蔬菜长成!

 

4.创建式模式之建造者模式                                                                                                                                          

对于建造者模式而已,它主要是将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。适用于那些产品对象的内部结构比较复杂。

建造者模式将复杂产品的构建过程封装分解在不同的方法中,使得创建过程非常清晰,能够让我们更加精确的控制复杂产品对象的创建过程,同时它隔离了复杂产品对象的创建和使用,使得相同的创建过程能够创建不同的产品。但是如果某个产品的内部结构过于复杂,将会导致整个系统变得非常庞大,不利于控制,同时若几个产品之间存在较大的差异,则不适用建造者模式,毕竟这个世界上存在相同点大的两个产品并不是很多,所以它的使用范围有限。其UML结构图:

 

 生活中这样的例子很多,如游戏中的不同角色,其性别、个性、能力、脸型、体型、服装、发型等特性都有所差异;还有汽车中的方向盘、发动机、车架、轮胎等部件也多种多样;每封电子邮件的发件人、收件人、主题、内容、附件等内容也各不相同。

以上所有这些产品都是由多个部件构成的,各个部件可以灵活选择,但其创建步骤都大同小异。这类产品的创建无法用前面介绍的工厂模式描述,只有建造者模式可以很好地描述该类产品的创建。

1、模式的定义与特点

建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

该模式的主要优点如下:

  1. 封装性好,构建和表示分离。
  2. 扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
  3. 客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。


其缺点如下:

  1. 产品的组成部分必须相同,这限制了其使用范围。
  2. 如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。


建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。

2、模式的结构与实现

建造者(Builder)模式由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成,现在我们来分析其基本结构和实现方法。

1. 模式的结构

建造者(Builder)模式的主要角色如下。

  1. 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
  2. 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
  3. 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
  4. 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。


其结构图如图 1 所示。

3、模式的应用场景
建造者模式唯一区别于工厂模式的是针对复杂对象的创建。也就是说,如果创建简单对象,通常都是使用工厂模式进行创建,而如果创建复杂对象,就可以考虑使用建造者模式。

当需要创建的产品具备复杂创建过程时,可以抽取出共性创建过程,然后交由具体实现类自定义创建流程,使得同样的创建行为可以生产出不同的产品,分离了创建与表示,使创建产品的灵活性大大增加。

建造者模式主要适用于以下应用场景:
  • 相同的方法,不同的执行顺序,产生不同的结果。
  • 多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同。
  • 产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用。
  • 初始化一个对象特别复杂,参数多,而且很多参数都具有默认值。
4、建造者模式和工厂模式的区别
    • 建造者模式更加注重方法的调用顺序,工厂模式注重创建对象。
    • 创建对象的力度不同,建造者模式创建复杂的对象,由各种复杂的部件组成,工厂模式创建出来的对象都一样
    • 关注重点不一样,工厂模式只需要把对象创建出来就可以了,而建造者模式不仅要创建出对象,还要知道对象由哪些部件组成。
    • 建造者模式根据建造过程中的顺序不一样,最终对象部件组成也不一样。

 

 

 5、创建式模型之建造者模式示例使用

【例1】用建造者(Builder)模式组装一辆汽车,包括许多组件,发动机、轮胎、车架等
首先我们要创建一个汽车的组件类,声明各种汽车的组件。汽车的各个组件定义成了一个个类,通过在组件类中声明有参构造器来注入汽车各种组件的商标,也可以通过set方法注入,这里使用构造器注入。同时通过get方法获取宝马汽车的各种组件的商标。

 

 

 1、产品角色之汽车
package DesignModel.CreatedModel.Builder;
//汽车组件类,声明汽车各种组件
public class Car {
    private Engine engine;//引擎
    private Tyre tyre;//轮胎
    private Frame frame;//车架

    public Engine getEngine() {
        return engine;
    }
    public void setEngine(Engine engine) {
        this.engine = engine;
    }
    public Tyre getTyre() {
        return tyre;
    }
    public void setTyre(Tyre tyre) {
        this.tyre = tyre;
    }
    public Frame getFrame() {
        return frame;
    }
    public void setFrame(Frame frame) {
        this.frame = frame;
    }
}
//引擎类
class Engine {
    private String name;
    public Engine(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//轮胎类
class Tyre {
    private String name;
    public Tyre(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
//车架类
class Frame {
    private String name;
    public Frame(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
2、抽象建造者之汽车建造者
package DesignModel.CreatedModel.Builder;
//汽车建造者
public interface CarBuilder {
    //构建汽车引擎
    public Engine builderEngine();
    //构建汽车轮胎
    public Tyre builderTyre();
    //构建汽车车架
    public Frame builderFrame();
}
3、具体建造者之宝马建造者
public class BwmBuilder implements CarBuilder {

    @Override
    public Engine builderEngine() {
        //也可通过工厂模式,单例模式等创建
        return new Engine("宝马发动机!");
    }
    @Override
    public Tyre builderTyre() {
        return new Tyre("宝马轮胎");
    }
    @Override
    public Frame builderFrame() {
        return new Frame("宝马车架");
    }
}
4、指挥者之指挥汽车和建造者的宝马领导协助者
package DesignModel.CreatedModel.Builder;
public interface CarDirector {
    //组装设计汽车
    public Car directorCar();
}
class BwmDirector implements CarDirector{
    private CarBuilder builder;
    public BwmDirector(CarBuilder builder) {
        this.builder  = builder;
    }

    @Override
    public Car directorCar() {
        //获取组件
        Engine engine = builder.builderEngine();
        Tyre tyre = builder.builderTyre();
        Frame frame = builder.builderFrame();
        //组装构建bwm汽车
        Car bwmCar = new Car();
        bwmCar.setEngine(engine);
        bwmCar.setTyre(tyre);
        bwmCar.setFrame(frame);

        return bwmCar;

    }
}
5、测试与实现
package DesignModel.CreatedModel.Builder;

/**
 * @program: FlinkUdf
 * @description: 建造者示例测试实现
 * @author: BigData
 * @create: 2020-11-30 18:19
 **/
public class Client {
    public static void main(String[] args) {
        //获取宝马汽车设计器
        BwmDirector carDirector = new BwmDirector(new BwmBuilder());
        //设计组装
        Car car = carDirector.directorCar();
        //查看汽车各种组件商标
        System.out.println("汽车引擎:"+car.getEngine().getName());
        System.out.println("汽车轮胎:"+car.getTyre().getName());
        System.out.println("汽车车架:"+car.getFrame().getName());
    }
}

结果:

"C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=53968:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\defaultuser0\AppData\Local\Temp\classpath222001828.jar DesignModel.CreatedModel.Builder.Client
汽车引擎:宝马发动机!
汽车轮胎:宝马轮胎
汽车车架:宝马车架

Process finished with exit code 0

 

5.创建式模式之原型模式                                                                                                                                             

在我们应用程序可能有某些对象的结构比较复杂,但是我们又需要频繁的使用它们,如果这个时候我们来不断的新建这个对象势必会大大损耗系统内存的,这个时候我们需要使用原型模式来对这个结构复杂又要频繁使用的对象进行克隆。所以原型模式就是用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。

它主要应用与那些创建新对象的成本过大时。它的主要优点就是简化了新对象的创建过程,提高了效率,同时原型模式提供了简化的创建结构。UML结构图:

 

 

 

 

1、意图:

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

2、主要解决:

在运行期建立和删除原型。

3、何时使用: 

1、当一个系统应该独立于它的产品创建,构成和表示时。

2、当要实例化的类是在运行时刻指定时,例如,通过动态装载。

3、为了避免创建一个与产品类层次平行的工厂类层次时。

4、当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。

4、如何解决:

利用已有的一个原型对象,快速地生成和原型对象一样的实例。

5、关键代码: 

1、实现克隆操作,在 JAVA 继承 Cloneable,重写 clone(),在 .NET 中可以使用 Object 类的 MemberwiseClone() 方法来实现对象的浅拷贝或通过序列化的方式来实现深拷贝。

2、原型模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些"易变类"拥有稳定的接口。

6、应用实例:

 1、细胞分裂。

2、JAVA 中的 Object clone() 方法。

7、优点:

 1、性能提高。

2、逃避构造函数的约束。

8、缺点:

1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。

2、必须实现 Cloneable 接口。

9、使用场景: 

1、资源优化场景。

2、类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。 3、性能和安全要求的场景。 4、通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。 5、一个对象多个修改者的场景。 6、一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。 7、在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用。

10、注意事项:

与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。

11. 模式的结构

原型模式包含以下主要角色。

  1. 抽象原型类:规定了具体原型对象必须实现的接口。
  2. 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
  3. 访问类:使用具体原型类中的 clone() 方法来复制新的对象。

12、代码应用实现
1、【例1】用原型模式模拟“孙悟空”复制自己。

分析:孙悟空拔下猴毛轻轻一吹就变出很多孙悟空,这实际上是用到了原型模式。这里的孙悟空类 SunWukong 是具体原型类,而 Java 中的 Cloneable 接口是抽象原型类。

同前面介绍的猪八戒实例一样,所以将孙悟空类定义成面板 JPanel 的子类,里面包含了标签,用于保存孙悟空的图像。

另外,重写了 Cloneable 接口的 clone() 方法,用于复制新的孙悟空。访问类可以通过调用孙悟空的 clone() 方法复制多个孙悟空,并在框架窗体 JFrame 中显示。图 2 所示是其结构图。

①、模型图

 

 

 ②、代码实现
package DesignModel.CreatedModel.ProtoModel;

import javax.swing.*;
import java.awt.*;

//抽象工厂
class SunWukong extends JPanel implements Cloneable
{
    private static final long serialVersionUID = 5543049531872119328L;
    public SunWukong() {
        JLabel jLabel=new JLabel(new ImageIcon("src/Img/Wukong.jpg"));
        this.add(jLabel);
    }
    /**
    * @Description: 克隆方法
    * @Param: []
    * @return: java.lang.Object
    * @Author: BigData
    * @Date: 2020/12/1
    */
    public Object clone()
    {
        SunWukong sunWukong=null;
        try {
            sunWukong= (SunWukong) super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println("拷贝孙悟空失败!"+e.getMessage());
        }
        return sunWukong;
    }
}

public class ProtoTypeWukong
{
    public static void main(String[] args) {
        JFrame jf=new JFrame("原型模式测试");
        jf.setLayout(new GridLayout(1,2));
        Container contentPane=jf.getContentPane();
        SunWukong sunWukong=new SunWukong();
        contentPane.add(sunWukong);
        SunWukong sunWukong1= (SunWukong) sunWukong.clone();
        contentPane.add(sunWukong1);
        jf.pack();
        jf.setVisible(true);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

结果:

 

 

 

 2、用原型模式生成“三好学生”奖状。

分析:同一学校的“三好学生”奖状除了获奖人姓名不同,其他都相同,属于相似对象的复制,同样可以用原型模式创建,然后再做简单修改就可以了。图 4 所示是三好学生奖状生成器的结构图。

 

 

 ①、代码实现
package DesignModel.CreatedModel.ProtoModel;

/**
 * @program: FlinkUdf
 * @description: 复制三号学生奖状,实现相似
 * @author: BigData
 * @create: 2020-12-01 09:52
 **/
public class ProtoTypeCitation {
    public static void main(String[] args) {
        citation obj1=new citation("张三","同学:在2020学年第一学期中表现优秀,被评为三好学生。","韶关学院");
        obj1.display();
        citation obj2=(citation) obj1.clone();
        obj2.setName("李四");
        obj2.display();
        citation obj3= (citation) obj1.clone();
        obj3.setName("王五");
        obj3.display();
    }
}
//奖状类
class citation implements Cloneable
{
    String name;
    String info;
    String college;

    public citation(String name, String info, String college) {
        this.name = name;
        this.info = info;
        this.college = college;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public void display()
    {
        System.out.println(name+info+college);
    }
    public Object clone()
    {
        try {
            System.out.println("拷贝奖状成功!!");
            return  (citation)super.clone();
        }
        catch (Exception e)
        {
            System.out.println("拷贝奖状失败!"+e.getMessage());
        }
        return "";
    }
}

结果:

"C:\Program Files\Java\jdk1.8.0_221\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=61784:C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\defaultuser0\AppData\Local\Temp\classpath1846184173.jar DesignModel.CreatedModel.ProtoModel.ProtoTypeCitation
张三同学:在2020学年第一学期中表现优秀,被评为三好学生。韶关学院
拷贝奖状成功!!
李四同学:在2020学年第一学期中表现优秀,被评为三好学生。韶关学院
拷贝奖状成功!!
王五同学:在2020学年第一学期中表现优秀,被评为三好学生。韶关学院

Process finished with exit code 0

 

 posted on 2020-12-01 10:01  大码王  阅读(327)  评论(0编辑  收藏  举报
复制代码