今天狠狠的学一下Java设计模式!

it2024-12-06  13

设计模式的本质是什么? 设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。

设计模式有两种分类方法,即根据模式的目的来分和根据模式的作用的范围来分。

根据目的来分 根据模式是用来完成什么工作来划分,这种方式可分为创建型模式、结构型模式和行为型模式 3 种。 创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。GoF 中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。 结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,GoF 中提供了代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。GoF 中提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。根据作用范围来分 根据模式是主要用于类上还是主要用于对象上来分,这种方式可分为类模式和对象模式两种。 类模式:用于处理类与子类之间的关系,这些关系通过继承来建立,是静态的,在编译时刻便确定下来了。GoF中的工厂方法、(类)适配器、模板方法、解释器属于该模式。 对象模式:用于处理对象之间的关系,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性。GoF 中除了以上 4 种,其他的都是对象模式。

单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。 原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。 工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。 抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。 建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。 代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。 适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。 桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。 装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。 享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。 组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。 模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。 职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。 状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。 观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。 中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。 迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。 访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。 备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。 解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。

面向对象设计原则:

开闭原则: 软件实体应当对扩展开放,对修改关闭

可以通过“抽象约束、封装变化”来实现开闭原则,即通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中。

里氏替换原则: 里氏替换原则通俗来讲就是:子类可以扩展父类的功能,但不能改变父类原有的功能。

依赖倒置原则: 通过要面向接口的编程来降低类间的耦合性。

单一职责原则: 发现类的不同职责并将其分离,再封装到不同的类或模块中。

接口隔离原则: 接口分的细一点

迪米特法则: 实体使用Get、Set方法,降低耦合度

合成复用原则:

合成复用原则是通过将已有的对象纳入新对象中,作为新对象的成员对象来实现的,新对象可以调用已有对象的功能,从而达到复用。

这 7 种设计原则是软件设计模式必须尽量遵循的原则,各种原则要求的侧重点不同。其中,开闭原则是总纲,它告诉我们要对扩展开放,对修改关闭;里氏替换原则告诉我们不要破坏继承体系;依赖倒置原则告诉我们要面向接口编程;单一职责原则告诉我们实现类要职责单一;接口隔离原则告诉我们在设计接口的时候要精简单一;迪米特法则告诉我们要降低耦合度;合成复用原则告诉我们要优先使用组合或者聚合关系复用,少用继承关系复用。

单例模式: 单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。

单例模式的优点: 单例模式可以保证内存里只有一个实例,减少了内存的开销。 可以避免对资源的多重占用。 单例模式设置全局访问点,可以优化和共享资源的访问。

单例模式的缺点: 单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则。 在并发测试中,单例模式不利于代码调试。在调试过程中,如果单例中的代码没有执行完,也不能模拟生成一个新的对象。 单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。

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

懒汉: public class LazySingleton { private static volatile LazySingleton instance=null; //保证 instance 在所有线程中同步 private LazySingleton(){} //private 避免类在外部被实例化 public static synchronized LazySingleton getInstance() { //getInstance 方法前加同步 if(instance==null) { instance=new LazySingleton(); } return instance; } }

饿汉: public class HungrySingleton { private static final HungrySingleton instance=new HungrySingleton(); private HungrySingleton(){} public static HungrySingleton getInstance() { return instance; } }

原型模式 //具体原型类 class Realizetype implements Cloneable { Realizetype() { System.out.println(“具体原型创建成功!”); } public Object clone() throws CloneNotSupportedException { System.out.println(“具体原型复制成功!”); return (Realizetype)super.clone(); } } //原型模式的测试类 public class PrototypeTest { public static void main(String[] args)throws CloneNotSupportedException { Realizetype obj1=new Realizetype(); Realizetype obj2=(Realizetype)obj1.clone(); System.out.println("obj1obj2?"+(obj1obj2)); } }

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

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

简单工厂模式 工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。 违背了开闭原则 对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。

public class Client { public static void main(String[] args) { } //抽象产品 public interface Product { void show(); } //具体产品:ProductA static class ConcreteProduct1 implements Product { public void show() { System.out.println(“具体产品1显示…”); } } //具体产品:ProductB static class ConcreteProduct2 implements Product { public void show() { System.out.println(“具体产品2显示…”); } } final class Const { static final int PRODUCT_A = 0; static final int PRODUCT_B = 1; static final int PRODUCT_C = 2; } static class SimpleFactory { public static Product makeProduct(int kind) { switch (kind) { case Const.PRODUCT_A: return new ConcreteProduct1(); case Const.PRODUCT_B: return new ConcreteProduct2(); } return null; } } }

工厂方法模式

package FactoryMethod;

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

public class AnimalFarmTest { public static void main(String[] args) { try { Animal a; AnimalFarm af; af = (AnimalFarm) ReadXML2.getObject(); a = af.newAnimal(); a.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/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/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(); } }

抽象工厂模式 前面介绍的工厂方法模式中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机、计算机软件学院只培养计算机软件专业的学生等。

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

本节要介绍的抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族,图 1 所示的是海尔工厂和 TCL 工厂所生产的电视机与空调对应的关系图。

创建者模式: 例如,计算机是由 CPU、主板、内存、硬盘、显卡、机箱、显示器、键盘、鼠标等部件组装而成的,采购员不可能自己去组装计算机,而是将计算机的配置要求告诉计算机销售公司,计算机销售公司安排技术人员去组装计算机,然后再交给要买计算机的采购员。

(1) 产品角色:包含多个组成部件的复杂对象。 class Product { private String partA; private String partB; private String partC; public void setPartA(String partA) { this.partA=partA; } public void setPartB(String partB) { this.partB=partB; } public void setPartC(String partC) { this.partC=partC; } public void show() { //显示产品的特性 } }

(2) 抽象建造者:包含创建产品各个子部件的抽象方法。 abstract class Builder { //创建产品对象 protected Product product=new Product(); public abstract void buildPartA(); public abstract void buildPartB(); public abstract void buildPartC(); //返回产品对象 public Product getResult() { return product; } }

(3) 具体建造者:实现了抽象建造者接口。 public class ConcreteBuilder extends Builder { public void buildPartA() { product.setPartA(“建造 PartA”); } public void buildPartB() { product.setPartB(“建造 PartB”); } public void buildPartC() { product.setPartC(“建造 PartC”); } }

(4) 指挥者:调用建造者中的方法完成复杂对象的创建。 class Director { private Builder builder; public Director(Builder builder) { this.builder=builder; } //产品构建与组装方法 public Product construct() { builder.buildPartA(); builder.buildPartB(); builder.buildPartC(); return builder.getResult(); } }

(5) 客户类。 纯文本复制 public class Client { public static void main(String[] args) { Builder builder=new ConcreteBuilder(); Director director=new Director(builder); Product product=director.construct(); product.show(); } }

太累了,改天再继续写。

最新回复(0)