设计模式(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)
原则是尽量使用合成、聚合的方式,而不是使用继承。
创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。
结构型模式:把类或对象结合在一起形成一个更大的结构。
行为型模式:类和对象如何交互,及划分责任和算法。
如下图所示:
单例模式,它的定义就是确保某一个类只有一个实例,并且提供一个全局访问点。
单例模式的主要角色如下。
因此当系统中只需要一个实例对象或者系统中只允许一个公共访问点,除了这个公共访问点外,不能通过其他访问点访问该实例时,可以使用单例模式。
单例模式的主要优点就是节约系统资源、提高了系统效率,同时也能够严格控制客户对它的访问。也许就是因为系统中只有一个实例,这样就导致了单例类的职责过重,违背了“单一职责原则”,同时也没有抽象类,所以扩展起来有一定的困难。其UML结构图非常简单,就只有一个类,如下图:
区别1:懒汉的特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例,相当于饭来张口。但饿汉式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。
区别2:懒汉式如果编写的是多线程程序,则不要删除上例代码中的关键字 volatile 和 synchronized,否则将存在线程非安全的问题。如果不删除这两个关键字就能保证线程安全,但是每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。但饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题。
相同点:属性类型和方法返回类型都是自身本类,且构造方法和方法都无参型。
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("我是美国总统:特朗普。"); } }
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; } }
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
产生一个总统!
我是美国总统:特朗普。
已经有一个总统,不能产生新总统!
我是美国总统:特朗普。
他们是同一个人
他们是同一人!
作为抽象工厂模式的孪生兄弟,工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个,也就是说工厂方法模式让实例化推迟到子类。
工厂方法模式非常符合“开闭原则”,当需要增加一个新的产品时,我们只需要增加一个具体的产品类和与之对应的具体工厂即可,无须修改原有系统。同时在工厂方法模式中用户只需要知道生产产品的具体工厂即可,无须关系产品的创建过程,甚至连具体的产品类名称都不需要知道。虽然他很好的符合了“开闭原则”,但是由于每新增一个新产品时就需要增加两个类,这样势必会导致系统的复杂度增加。其UML结构图:
工厂方法模式的主要角色如下。
其结构图如图 1 所示。
【例1】用工厂方法模式设计畜牧场。
分析:有很多种类的畜牧场,如养马场用于养马,养牛场用于养牛,所以该实例用工厂方法模式比较适合。
对养马场和养牛场等具体工厂类,只要定义一个生成动物的方法 newAnimal() 即可。由于要显示马类和牛类等具体产品类的图像,所以它们的构造函数中用到了 JPanel、JLabd 和 ImageIcon 等组件,并定义一个 show() 方法来显示它们。
客户端程序通过对象生成器类 ReadXML2 读取 XML 配置文件中的数据来决定养马还是养牛。其结构图如图 2 所示。
package DesignModel.CreatedModel.FactoryMethod; /** * @program: FlinkUdf * @description: 抽象产品:动物类 * @author: BigData * @create: 2020-11-30 10:50 **/ public interface Animal { public void show(); }
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); } }
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); } }
package DesignModel.CreatedModel.FactoryMethod; //抽象工厂:畜牧场 public interface AnimalFarm { public Animal newAnimal(); }
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(); } }
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(); } }
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
新马出生!
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; } } }
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(); } }
所谓抽象工厂模式就是提供一个接口,用于创建相关或者依赖对象的家族,而不需要明确指定具体类。他允许客户端使用抽象的接口来创建一组相关的产品,而不需要关系实际产出的具体产品是什么。这样一来,客户就可以从具体的产品中被解耦。它的优点是隔离了具体类的生成,使得客户端不需要知道什么被创建了,而缺点就在于新增新的行为会比较麻烦,因为当添加一个新的产品对象时,需要更加需要更改接口及其下所有子类。其UML结构图如下:
将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,图 1 所示的是海尔工厂和 TCL 工厂所生产的电视机与空调对应的关系图。
抽象工厂(AbstractFactory)模式的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
使用抽象工厂模式一般要满足以下条件。
抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。
其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。增加了系统的抽象性和理解难度。
抽象工厂模式同工厂方法模式一样,也是由抽象工厂、具体工厂、抽象产品和具体产品等 4 个要素构成,但抽象工厂中方法个数不同,抽象产品的个数也不同。现在我们来分析其基本结构和实现方法。
抽象工厂模式的主要角色如下。
抽象工厂模式的结构图如图 2 所示。
【例1】用抽象工厂模式设计农场类。
分析:农场中除了像畜牧场一样可以养动物,还可以培养植物,如养马、养牛、种菜、种水果等,所以本实例比前面介绍的畜牧场类复杂,必须用抽象工厂模式来实现。
本例用抽象工厂模式来设计两个农场,一个是韶关农场用于养牛和种菜,一个是上饶农场用于养马和种水果,可以在以上两个农场中定义一个生成动物的方法 newAnimal() 和一个培养植物的方法 newPlant()。
package DesignModel.CreatedModel.AbstractFactory; /** * @program: FlinkUdf * @description: 抽象产品:动物类 * @author: BigData * @create: 2020-11-30 10:50 **/ public interface Animal { public void show(); }
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); } }
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); } }
package DesignModel.CreatedModel.AbstractFactory; /** * 抽象产品:植物类 */ public interface Plant { public void show(); }
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); } }
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); } }
package DesignModel.CreatedModel.AbstractFactory; //抽象工厂:农场类 public interface Farm { public Animal newAnimal(); public Plant newPlant(); }
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(); } }
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(); } }
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()); } } }
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
新牛出生!
蔬菜长成!
对于建造者模式而已,它主要是将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。适用于那些产品对象的内部结构比较复杂。
建造者模式将复杂产品的构建过程封装分解在不同的方法中,使得创建过程非常清晰,能够让我们更加精确的控制复杂产品对象的创建过程,同时它隔离了复杂产品对象的创建和使用,使得相同的创建过程能够创建不同的产品。但是如果某个产品的内部结构过于复杂,将会导致整个系统变得非常庞大,不利于控制,同时若几个产品之间存在较大的差异,则不适用建造者模式,毕竟这个世界上存在相同点大的两个产品并不是很多,所以它的使用范围有限。其UML结构图:
生活中这样的例子很多,如游戏中的不同角色,其性别、个性、能力、脸型、体型、服装、发型等特性都有所差异;还有汽车中的方向盘、发动机、车架、轮胎等部件也多种多样;每封电子邮件的发件人、收件人、主题、内容、附件等内容也各不相同。
以上所有这些产品都是由多个部件构成的,各个部件可以灵活选择,但其创建步骤都大同小异。这类产品的创建无法用前面介绍的工厂模式描述,只有建造者模式可以很好地描述该类产品的创建。
建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
该模式的主要优点如下:
其缺点如下:
建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。
建造者(Builder)模式由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成,现在我们来分析其基本结构和实现方法。
建造者(Builder)模式的主要角色如下。
其结构图如图 1 所示。
【例1】用建造者(Builder)模式组装一辆汽车,包括许多组件,发动机、轮胎、车架等
首先我们要创建一个汽车的组件类,声明各种汽车的组件。汽车的各个组件定义成了一个个类,通过在组件类中声明有参构造器来注入汽车各种组件的商标,也可以通过set方法注入,这里使用构造器注入。同时通过get方法获取宝马汽车的各种组件的商标。
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; } }
package DesignModel.CreatedModel.Builder; //汽车建造者 public interface CarBuilder { //构建汽车引擎 public Engine builderEngine(); //构建汽车轮胎 public Tyre builderTyre(); //构建汽车车架 public Frame builderFrame(); }
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("宝马车架"); } }
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; } }
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
在我们应用程序可能有某些对象的结构比较复杂,但是我们又需要频繁的使用它们,如果这个时候我们来不断的新建这个对象势必会大大损耗系统内存的,这个时候我们需要使用原型模式来对这个结构复杂又要频繁使用的对象进行克隆。所以原型模式就是用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
它主要应用与那些创建新对象的成本过大时。它的主要优点就是简化了新对象的创建过程,提高了效率,同时原型模式提供了简化的创建结构。UML结构图:
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;
}
}
}
宝马
Java从入门到实战之(33)Java中23种设计模式之6种创建式模式
原文:https://www.cnblogs.com/huanghanyu/p/14049713.html