设计模式
- 前言
-
- 模式分类
- 设计原则
-
- 单一职责原则
- 开闭原则
- 依靠倒置原则
- 接口分离原理
- 迪米特法则
- 替氏替换原则
- 合成复用原则
- 创建型模式
-
- 工厂模式(简单工厂、工厂方法、抽象工厂)
- 单例模式
- 原型模式
- 建造者模式
- 总结
- 结构型模式
-
- 适配器模式
- 代理模式
- 桥接模式
- 装饰模式
- 外观模式
- 享元模式
- 组合模式
- 总结
- 行为型模式
-
- 模板方法模式
- 策略模式
- 命令模式
- 职责链模式
- 状态模式
- 观察者模式
- 中介者模式
- 迭代器模式
- 访问者模式
- 备忘录模式
- 解释器模式
- 总结
- 本章小结
前言
模式似乎不同于传统的分析、设计和实现思维方式。相反,模型在程序中反映了一个完整的想法,因此有时会出现在分析阶段或高级设计阶段。由于该模型直接在代码中实现,您可能不会期望该模型在低级设计或实现之前出现(通常在达到这些阶段之前,您不会意识到需要一个特定的模型)。模型的基本概念也可以看作是程序设计的基本概念:添加抽象层。当你抽象一些东西时,就像剥离特定的细节,这背后最重要的动机之一是:
将易变的事物与不变的事物分开
另一种方法是,一旦您发现程序的某些部分可能会因某种原因而改变,您应该保持这些变化不会导致整个代码中的其他变化。 如果代码更容易理解,则更容易维护。
设计模式的目标是在隔离代码中更改
模式分类
根据模式,设计模式有两种分类方法根据模式进行分和来分。
- :如何创建对象。 这通常涉及到隔离对象创建的细节,因此您的代码不依赖于特定对象的类型,因此在添加新类型的对象时不会更改。其主要特点是将对象的创建和使用分开。设计模式 中提供了等 5 创建模式。
- :设计对象以满足特定的项目约束。它们处理对象与其他对象的连接,以确保系统中的变化不需要更改这些连接。用于描述如何根据某种布局形成更大的类别或对象结构 中提供了等 7 结构模式。
- :用于描述如何相互合作或完成单个对象不能单独完成的任务,以及如何分配责任。设计模式 中提供了等 11 行为模式。
根据模式是主要用于类别还是主要用于对象,可分为和两种。
- :用于处理类与子之间的关系,这些关系是通过继承建立的,是静态的,在编译时刻就确定了。设计模式 中的属于该模式。
- :这些关系可以通过组合或聚合来处理对象之间的关系,在运行时间可以改变,更加动态。设计模式 中除了以上 4 其他的都是对象模式。
设计原则
软件系统设计中应遵循的一些经验标准通常是为了避免一些经常出现的设计缺陷。目前,公认的设计原则包括:等。
单一职责原则
一个类(模块)只负责一个功能领域的相应责任。对于一个类(模块),应该只有一个原因导致它的变化。
在软件开发中,随着需求的不断增加,可能会给原来的类别增加一些不属于它的责任,从而违反了单一责任的原则。如果我们发现目前不仅有一种责任,我们就应该把不属于这种真正的责任分开。不仅是类,函数也遵循单一职责的原则,即一个函数做一件事。如果发现函数中有不同的任务,则需要以另一个函数的形式分离不同的任务。从此实现代码的高内聚和低耦合。
开闭原则
扩大开放,修改关闭。
添加新功能应通过扩展代码(新模块、类别、方法、属性等)而不是修改现有代码(修改模块、类别、方法、属性等)来完成。增加了程序的可扩展性,降低了程序的维护成本。
依靠倒置原则
高层模块不应依赖低层模块,而应依赖其抽象。抽象不应该依赖细节,细节应该依赖抽象()。
通过抽象构建框架,构建类与类之间的关联,以减少类之间的耦合。此外,抽象系统比具体系统更稳定、更可扩展、更容易维护。
接口分离原则
使用多个特殊总接口的情况下,使用多个特殊接口,即客户端不应依赖其不需要的接口()。
如果不建立庞大臃肿的接口,应尽量细化接口,将臃肿的接口分成几个小接口,通过小接口的不同组合可以满足更多的需求。接口责任划分更加明确,符合高内聚低耦合的理念。
迪米特法则
迪米特法则(Law of Demeter, LoD)也被称为最低知识原则,是1987年秋天lan holland在美国东北大学,一个叫迪米特的项目设计。一个类别对其他类别的了解越少越好,也就是说,一个对象应该尽可能少地了解其他对象,只与朋友沟通,不与陌生人交谈()。
每个对象都会与其他对象耦合。只要两个对象之间有耦合,我们就会说这两个对象是朋友。一个类别应该只与其成员变量、方法输入和返回参数中的类别进行交流,而不是引入其他类别(间接交流)。
替氏替换原则
子类必须出现在任何基类可以出现的地方()。
将一个基类对象替换成它的子类对象,程序将不会产生任何错误和异常,反过来则不成立,如果是子类对象的话,那么它不一定能够使用基类对象。里氏代换原则是对 开闭原则 补充 开闭原则 关键步骤是抽象化。基类与子类的继承关系是抽象化的具体实现,因此里氏替代原则是抽象化具体步骤的标准化。
合成复用原则
合成复用原则又称组合复用原则(Composition/Aggregate Reuse Principle, CARP),要求在软件复用时尽一切努力先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。如果要使用继承关系,则必须严格遵循里氏代换原则。合成复用原则同里氏替换原则相辅相成的,两者都是开闭原则的具体实现规范。
通过继承来进行复用,由于基类的内部细节通常对子类来说是可见的,如果基类发生改变,那么子类的实现也不得不发生改变。合成复用原则可以将已有的对象(也可称为成员对象)纳入到新对象中,使之成为新对象的一部分,因此新对象可以调用已有对象的功能,这样做可以使得成员对象的内部实现细节对于新对象不可见,相对继承关系而言,其耦合度相对较低,成员对象的变化对新对象的影响不大。合成复用原则可以在运行时动态进行,新对象可以动态地引用与成员对象类型相同的其他对象。
创建型模式
将对象的创建与使用分离
工厂模式(简单工厂、工厂方法、抽象工厂)
通常创建的对象称为“产品”,把创建产品的对象称为“工厂”。简单工厂模式中创建实例的方法通常为静态(static)方法,所以(Simple Factory Pattern)又叫作(Static Factory Method Pattern)。
以生产产品为例,示例代码如下:
//产品
public class Product {
public Product (){
System.out.println("产品");
}
}
//产品A
public class ProductA extends Product{
public ProductA() {
System.out.println("产品A");
}
}
//产品B
public class ProductB extends Product {
public ProductB() {
System.out.println("产品B");
}
}
//工厂
public class Factory {
public static Product create(String type){
if("A".equals(type)){
return new ProductA();
}else if("B".equals(type)){
return new ProductB();
}
return null;
}
public static void main(String[] args) {
Product product = Factory.create("A");
/** Output: * 产品 * 产品A */
}
}
简易结构图:
简单工厂模式每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度,违背了“开闭原则”。
“”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
以生产产品为例,示例代码如下:
//产品
public class Product {
public Product (){
System.out.println("产品");
}
}
//产品A
public class ProductA extends Product{
public ProductA() {
System.out.println("产品A");
}
}
//产品B
public class ProductB extends Product {
public ProductB() {
System.out.println("产品B");
}
}
//工厂
public abstract class Factory {
public abstract Product create();
}
//工厂A
public class FactoryA extends Factory{
@Override
public ProductA create() {
return new ProductA();
}
}
//工厂B
public class FactoryB extends Factory{
@Override
public ProductB create() {
return new ProductB();
}
public static void main(String[] args) {
FactoryA factoryA = new FactoryA();
ProductA productA = factoryA.create();
FactoryB factoryB = new FactoryB();
ProductB productB = factoryB.create();
}
}
简易结构图:
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品,如农场里既养动物又种植物等。
的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
以生产产品为例,示例代码如下:
//产品
public class Product {
public Product (){
System.out.println("产品");
}
}
//产品A
public class ProductA extends Product{
public ProductA() {
System.out.println("产品A");
}
}
//产品B
public class ProductB extends Product {
public ProductB() {
System.out.println("产品B");
}
}
//零件
public class Part {
public Part() {
System.out.println("零件");
}
}
//零件A
public class PartA extends Part{
public PartA() {
System.out.println("零件A");
}
}
//零件B
public class PartB extends Part{
public PartB() {
System.out.println("零件B");
}
}
//工厂
public abstract class Factory {
public abstract Product createProduct();
public abstract Part createPrat();
}
//工厂A
public class FactoryA extends Factory{
@Override
public Product createProduct() {
return new ProductA();
}
@Override
public Part createPrat() {
return new PartA();
}
}
//工厂B
public class FactoryB extends Factory{
@Override
public Product createProduct() {
return new ProductB();
}
@Override
public Part createPrat() {
return new PartB();
}
public static void main(String[] args) {
FactoryA factoryA = new FactoryA();
factoryA.createProduct();
factoryA.createPrat();
FactoryB factoryB = new FactoryB();
factoryB.createProduct();
factoryB.createPrat();
/** Output: * 产品 * 产品A * 零件 * 零件A * 产品 * 产品B * 零件 * 零件B */
}
}
简易结构图:
需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则,当系统中只存在一个等级结构的产品时,抽象工厂模式将退化到工厂方法模式。
单例模式
指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。 通常,普通类的构造函数是公有的,外部类可以通过new constructor()
来生成多个实例。但是,如果将类的构造函数设为私有的,外部类就无法调用该构造函数,也就无法生成多个实例。这时该类自身必须定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态私有实例。 系统中只存在一个共用的实例对象,无需频繁创建和销毁对象,节约了系统资源,提高系统的性能。
示例代码如下:
public class Singleton {
private static volatile Singleton singleton = new Singleton();
private Singleton() {
}
public Singleton getInstance() {
return singleton;
}
}
饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的。
示例代码如下:
public class Singleton {
private static volatile Singleton singleton = null;
private Singleton(){
}
public Singleton getInstance(){
if(singleton == null){
synchronized (Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
的作用主要是禁止指定重排序。使用两个 判断,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗。
原型模式
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。
创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
示例代码如下:
public class A implements Cloneable{
private ArrayList arrayList;
@Override
protected Object clone() throws CloneNotSupportedException {
A clone = (A) super.clone();
return clone;
}
@Override
public String toString() {
return "[arrayList="+this.arrayList+"]";
}
public static void main(String[] args) throws CloneNotSupportedException {
ArrayList arrayList = new ArrayList();
arrayList.add("123");
A a = new A();
a.arrayList = arrayList ;
A clone = (A) a.clone();
System.out.println("原集合:"+a.arrayList);
System.out.println("复制集合:"+clone.arrayList);
arrayList.add("abc");
System.out.println("修改后原集合:"+a.arrayList);
System.out.println("修改后复制集合:"+clone.arrayList);
/** Output: * 原集合:[123] * 复制集合:[123] * 修改后原集合:[123, abc] * 修改后复制集合:[123, abc] */
}
}
由于指向同一个内存地址,所以修改数据也相同。
创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
示例代码如下:
public class A implements Cloneable{
private ArrayList arrayList;
@Override
protected Object clone() throws CloneNotSupportedException {
A clone = (A) super.clone();
clone.arrayList = (ArrayList) arrayList.clone();
return clone;
}
@Override
public String toString() {
return "[arrayList="+this.arrayList+"]";
}
public static void main(String[] args) throws CloneNotSupportedException {
ArrayList arrayList = new ArrayList();
arrayList.add("123");
A a = new A();
a.arrayList = arrayList ;
A clone = (A) a.clone();
System.out.println("原集合:"+a.arrayList);
System.out.println("复制集合:"+clone.arrayList);
arrayList.add("abc");
System.out.println("修改后原集合:"+a.arrayList);
System.out.println("修改后复制集合:"+clone.arrayList);
/** Output: * 原集合:[123] * 复制集合:[123] * 修改后原集合:[123, abc] * 修改后复制集合:[123] */
}
}
原型模式需要为每一个类都配置一个 clone()
方法,clone()
方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
建造者模式
将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
示例代码如下:
//产品:指定有哪些产品 public class Product { private String a; private String b; public void setA(String a) { this.a = a; } public void setB(String b) { this.b = b; } @Override public String toString() { return "[a="+this.a+",b="+this.b+"]"; } } //产品的抽象 具体需要做哪些方法,得到什么产品 public abstract class ProductService { public abstract void productA(); public abstract void productB(); //获取产品结果 abstract Product getProduct(); } //产品的具体实现(建造者) public class ProductServiceImpl extends ProductService { Product product = new Product(); @Override public void productA() { product.setA("产品A"); } @Override public void productB() { product.setB("产品B"); } @Override Product getProduct() { return product; } } //指挥 public class Conduct { public ProductService conduct 标签:
电连接器插座的屏蔽构件sub4p插头连接器