设计模式

2020/08/23 设计模式 共 8670 字,约 25 分钟

1. 根据目的来分

设计模式

根据模式是用来完成什么工作来划分,这种方式可分为创建型模式、结构型模式和行为型模式 3 种。

  1. 创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。GoF 中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。
  2. 结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,GoF 中提供了代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。
  3. 行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。GoF 中提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。

2. 根据作用范围来分

根据模式是主要用于类上还是主要用于对象上来分,这种方式可分为类模式和对象模式两种。

  1. 类模式:用于处理类与子类之间的关系,这些关系通过继承来建立,是静态的,在编译时刻便确定下来了。GoF中的工厂方法、(类)适配器、模板方法、解释器属于该模式。
  2. 对象模式:用于处理对象之间的关系,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性。GoF 中除了以上 4 种,其他的都是对象模式。
范围\目的创建型模式结构型模式行为型模式
类模式工厂方法(类)适配器模板方法、解释器
对象模式单例 原型 抽象工厂 建造者代理 (对象)适配器 桥接 装饰 外观 享元 组合策略 命令 职责链 状态 观察者 中介者 迭代器 访问者 备忘录

具体设计模式

原文:https://www.runoob.com/design-pattern/singleton-pattern.html

前面说明了 GoF 的 23 种设计模式的分类,现在对各个模式的功能进行介绍。

  1. 单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。

    主要解决:一个全局使用的类频繁地创建与销毁。

    何时使用:当您想控制实例数目,节省系统资源的时候。

    如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。

    关键代码:构造函数是私有的。

  2. 原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。

  3. 工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。

    Connector factory创建

  4. 抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。

  5. 建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。

  6. 代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。

  7. 适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。

  8. 桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。

  9. 装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。

  10. 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。

  11. 享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。

  12. 组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。

  13. 模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。

  14. 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。

Kafka中TransportLayer 根据网络协议的不同,提供不同的子类,而对KafkaChannel提供统一的接口,这是策略模式的应用

  1. 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。

  2. 职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。

  3. 状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。

  4. 观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。

  5. 中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。

  6. 迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。

  7. 访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。

  8. 备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。

  9. 解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。

设计模式目的

编写软件过程中,程序员面临来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让程序具有:

  1. 代码重用性(相同功能的代码,不用多次编写)
  2. 可读性(变成规范,便于他人的阅读和理解)
  3. 可扩展性(当需要增加新的功能时,非常的方便)
  4. 可靠性(当我们增加新的功能后,对原来的功能没有影响)
  5. 高内聚,低耦合

创造者模式

单例模式

单例的对象必须只有一个实例存在,比如 配置 由一个单例对象统一读取,

public class Singleton {
	private static Singleton singleton = null;

	private Singleton(){

	}

	public synchronized  static Singleton getInstance(){
		if (singleton ==null){
			singleton = new Singleton();
		}
		return singleton;
	}
}

工厂

工厂模式的核心思想在是将类创建的权利授予给工厂类,其他的类不允许创建,授予了权限的类创建好之后,需要某些的对象的时候,可以去工厂当中去取。也就是像一个工厂一样,用的人不需要关心对象怎么来的,你只需要关心怎么用就好了

工厂方法

  1. 解决了哪类“工厂”生产哪类东西的问题。 2.这种模式通过公共的接口或抽象类定义生产出来的是哪种东西,但是不限制生产出来的具体产品,在其子类中或者实现类中去确定具体生产出来的是什么东西。

抽象工厂

  1. 解决了同一种东西多种分类的情况。
  2. 抽象类去设定生产的产品的具体分类,交给子类去实际生产该分类下的产品。

简单的讲,三者最主要的区别在于: 简单工厂:通过参数控制生产的不同的产品。 工厂方法:通过不同的子类工厂生产不同的产品。 抽象工厂:通过方法生产不同的产品。

public interface Factory {
	public Car createCar();
}


public class BMWFactory implements Factory{
	@Override
	public Car createCar() {
		return new BMWCar;
	}
}

创建者模式

生成器模式(英:Builder Pattern)是一种设计模式,又名:建造模式,是一种对象构建模式。它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象

public abstract class CarBuilder {
	protected  Car car = new Car();

	public abstract void setShape(String shape);
	public abstract void setColor(String color);
	public Car getCar(){
		return this.car;
	}
}

public class BMWCarBuilder extends CarBuilder {
	@Override
	public void setShape(String shape) {
		this.car.setShape(shape);
	}

	@Override
	public void setColor(String color) {
		this.car.setColor(color);
	}
}

原型模式

原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据。 注意: 1.原型模式创建对象不会调用构造函数进行创建。直接从内存去赋值对象的数据,忽略构造函数的限制,他和之前提到的单例模式有所冲突,单例模式会将构造函数设置为私有,而原型模式却可以绕过构造函数去通过内存中的对象的数据区创建对象,所以这个地方就会有所冲突。

就是 深 clone

结构型模式

用于描述如何将类或对象按某种布局组成更大的结构

适配器模式

将两个不一致或者说无法直接使用的类或者接口通过适配器模式进行兼容,使得他们可以在一块使用

public class UserInfoTransfer extends UserInfoFrom implements UserInfoIntoInterface {
	private Map<String, String> nameInfo = super.getUserInfo();
	private Map<String, String> addressInfo = super.getHomeAddress();


	@Override
	public UserInfoInto getUser() {
		UserInfoInto into = new UserInfoInto();
		into.setUserName(nameInfo.get("wy"));
		into.setAddress(addressInfo.get("wy"));

		return into;
	}
}

代理模式

代理模式就是找另外的一个对象作为代理去为你实施请求,代理模式分为两种,一种是静态代理模式,另外一种是动态代理模式,静态代理模式是代理类为其创建一个对象,将需要代理的类的对象赋予代理类中的该对象,让代理类中该对象去代替需要代理的类的对象去执行一定的任务。动态代理模式采用JDK的动态代理,根据其类加载器以及其实现的接口生成代理对象,通过反射机制实现动态代理

public class PDFProxy {
	public static Object getProxy(final Object obj){
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
				obj.getClass().getInterfaces(), new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						method.invoke(obj,args);
						return null;
					}
				});
	}
}

装饰模式

修饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。就功能而言,修饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能

public class ShapeDecorator implements  Shape{
	protected Shape decoratedShape;

	public ShapeDecorator (Shape decoratedShape){
		this.decoratedShape = decoratedShape;
	}
	@Override
	public void draw() {
		decoratedShape.draw();
	}
}

public class RedShapeDecorator extends ShapeDecorator
{
	public RedShapeDecorator(Shape decoratedShape) {
		super(decoratedShape);
	}

	@Override
	public void draw() {
		decoratedShape.draw();
		setRedBorder(decoratedShape);

	}
	private void setRedBorder(Shape decoratedShape) {
		System.out.println("Red = red");
	}
}

外观模式

当一个项目中出现比较杂乱的调用关系时,类与类之间的耦合关系过于复杂,为了降低耦合度,我们可以采用一个公共的接口与其他类发生耦合,这样可以尽量大的降低外界与该系统的耦合度,同时降低了整个系统的复杂度,外观模式相当于一个公共的入口一样,为使用者敞开大门,暴漏一些必要的接口,方便外界进行调用。通俗来讲就是,有多个不同的类提供了多个访问的接口,外观模式就是要统一将这些接口进行管理

public class ShapeMaker {
	private Shape circle;
	private Shape rectangle;

	public ShapeMaker(){
		circle = new Circle();
		rectangle = new Rectangle();
	}

	public void drawCircle(){
		circle.draw();
	}

	public void drawRectangle(){
		rectangle.draw();
	}
}

桥接模式

桥梁模式的核心在于解耦,通过抽象化将具体的事物抽象成一般的事物,也就是具有共性的东西,将两个角色之间的继承关系改为聚合关系,就是将它们之间的强关联改换成为弱关联。因此,桥梁模式中的所谓脱耦,就是指在一个软件系统的抽象化和实现化之间使用聚合关系而不是继承关系,从而使两者可以相对独立地变化。这就是桥梁模式的用意

/**
 * 创建桥接实现接口
 */
public interface DrawAPI {
	public void drawCircle(int radius,int x, int y);
}


public abstract class Shape {
	protected  DrawAPI drawAPI;

	protected Shape(DrawAPI drawAPI){
		this.drawAPI = drawAPI;
	}
	public abstract void draw();
}

public class Circle extends Shape{
	private int x,y,radius;

	protected Circle(int x,int y,int redius,DrawAPI drawAPI) {
		super(drawAPI);
		this.x = x;
		this.y = y;
		this.radius = radius;
	}

	@Override
	public void draw() {
		drawAPI.drawCircle(radius,x,y);
	}
}

组合模式

组合模式也叫合成模式,有时又叫做部分-整体模式,主要是用来描述部分与整体的关系,其定义为:将对象组合成树形结构以表示“整体与部分”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。—-设计模式之禅 个人理解 组合模式目的是将整体与部分组合成树形来表示整体与部分的层次,使得用户对单个对象和组合对象的使用具有一致性的接口,也就是通过接口对子对象统一操作

public class Employee {
	private String name;
	private String dept;
	private int salary;
	private List<Employee> subordinates;

	//构造函数
	public Employee(String name,String dept, int sal) {
		this.name = name;
		this.dept = dept;
		this.salary = sal;
		subordinates = new ArrayList<Employee>();
	}

	public void add(Employee e) {
		subordinates.add(e);
	}

	public void remove(Employee e) {
		subordinates.remove(e);
	}

	public List<Employee> getSubordinates(){
		return subordinates;
	}

	public String toString(){
		return ("Employee :[ Name : "+ name
				+", dept : "+ dept + ", salary :"
				+ salary+" ]");
	}
}

行为型模式

用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责

模板方法模式

一个算法的步骤,并允许子类别为一个或多个步骤提供其实践方式。让子类别在不改变算法架构的情况下,重新定义算法中的某些步骤

一般的都是由抽象类定义好模板方法,然后,子类通过继承并实现其父类中定义好的模板中需要执行的具体的方法,调用子类对象的模板方法时,会执行该类中的具体实现的方法。这个模式我个人的感觉有点像是面向过程的操作,执行完一道工序,接着下一道工序

public abstract class Game {
	abstract  void initialize();
	abstract  void startPlay();
	abstract  void endPlay();

	//模板
	public final void play(){
		//初始化游侠
		initialize();;
		//开始游戏
		startPlay();
		//结束游侠
		endPlay();
	}
}

public class Football extends Game {
	@Override
	void initialize() {

	}

	@Override
	void startPlay() {

	}

	@Override
	void endPlay() {

	}
}

观察者模式

观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统

public class Subject {

	private List<Observer> observers
			= new ArrayList<Observer>();
	private int state;

	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
		notifyAllObservers();
	}

	public void attach(Observer observer){
		observers.add(observer);
	}

	public void notifyAllObservers(){
		for (Observer observer : observers) {
			observer.update();
		}
	}
}

	public static void main(String[] args) throws Exception{
		Subject subject = new Subject();

		new OctalObserver(subject);
		new BinaryObserver(subject);

		System.out.println("First state change: 15");
		subject.setState(15);
		System.out.println("Second state change: 10");
		subject.setState(10);
	}

策略模式

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。


public interface Strategy {
	public int doOperation(int num1, int num2);
}


public class OperationAdd implements Strategy{
	@Override
	public int doOperation(int num1, int num2) {
		return num1+num2;
	}
}

文档信息

Search

    Table of Contents