OOAD之设计模式

版权声明:本篇文章由IT_CREATE整理 https://blog.csdn.net/IT_CREATE/article/details/83929987

一、模式:

避免重复问题,而提出来的解决方案。

模式又可以分为:

架构模式  

设计模式

 

1.1架构模式

软件架构的上,整体考虑,而提出来的一些解决方案,比如:三层架构,B/S,C/S,MVC,ORM,事务脚本,领域模型……,从宏观的角度上来说

 

1.2设计模式

设计模式是从微观的角度上来看待软件开发过程中,碰到的一些重复业务场景,并提出的解决方案。

 

设计模式:创建性设计模式,结构性设计模式,行为性设计模式

**创建性设计模式:**更多的关注对象如何创建,而提出来的各种创建方案

**结构性设计模式:**更多的关注于类和类,对象和对象的整体结构,而提出来的各种解决方案

**行为性设计模式:**更多的关注于实例之间的行为互调,以及职责分配的问题

 

1.2.1分类

*创建性设计模式中:**

简单工厂模式

静态工厂方法(Static Factory Method)

抽象工厂(Abstract Factory)

单例模式(Singleton)

原型模式(Prototype)

建造模式(Builder)

 

**结构性设计模式中:**

适配器模式(Adapter)

桥接模式(Bridge)

复合模式(Composite)

装饰器模式(Decorator)

外观模式(Façade)

享元模式(FlyWeight)

代理模式(Proxy)

 

**行为性设计模式:**

解释器模式(Interpreter)

模板方法模式(Template Method)

职责链模式(Chain of Responsibility)

命令模式(Command)

迭代器模式(Iterator)

中介者模式(Mediator)

备忘录模式(Memento)

观察者模式(Observer)

策略模式(Strategy)

状态模式(State)

访问者模式(Visitor)

 

1.2.1详细介绍

**1、简单工厂模式**

简单工厂模式,又被称之为“静态工厂方法”模式,该模式会专门定义一个“工厂类”,然后在工厂类提供一个静态方法,有该静态方法根据用户的输入,动态决定创建什么类型的对象。通常来说:工厂类的产生的对象,都有一个特点,具备相同的父类,或者具备相同的接口

简单工厂的3种角色:工厂类,产品的抽象类(接口),具体的产品

1)工厂类:主要负责根据用户的输入,动态的产生具体的产品

2)产品抽象类|接口:对具体产品进行类的抽象或者行为的抽象

3)具体的产品:工厂类产生的具体实例

简单工厂模式的作用:

将客户调用类上的2个职责(创建对象的职责,调用对象的行为的职责),进行职责分离,让调用类最终只存在1个职责(调用对象的行为的职责),而将创建对象的职责,委托给工厂类。

简单工厂模式的缺点:

简单工厂,实际上将对象的产生,由之前的客户调用类身上,强制性的定义在工厂类身上,工厂类此时具备一定的创建对象的业务逻辑,以及一些判断逻辑。那么如果具体的产品,需要发生变化,或者有新的产品需要扩展,那么毫无疑问,此时就需要去针对工厂类做相应的变化,那么无形当中就违背了“开闭原则”,“单一原则”,“依赖倒转原则”

注意:

简单工厂模式,只能产生同一家族(继承相同类,实现相同接口)的产品,非同一家族的产品,简单工厂是无法使用的。

 

**2、抽象工厂方法模式:**

简单工厂模式,会出现一些问题,比如:调用类和工厂类直接耦合(依赖倒转原则),工厂类中无法满足“开闭原则”,因为工厂类中方法存在一定的业务逻辑和判断逻辑,如果需要新增新的产品,工厂类也需要去做相应的修改,所以违背了“开闭原则”

为了规避上述问题,所以才有了抽象工厂方法模式,该模式实际上就是在工厂类的基础上,进一步进行工厂抽象,然后每一个独立的产品,都对应一个具体的产品工厂,通过这种方式来实现程序满足“开闭原则”

在调用类中使用面向接口编程,来解决上述的调用类和工厂类直接耦合的问题。

抽象工厂模式有4种角色:

1、工厂的抽象类  完成对产品生产工厂进行抽象

2、具体产品的生产工厂   分别对产品进行生产

3、产品抽象类|接口:对具体产品进行类的抽象或者行为的抽象

4、具体的产品:工厂类产生的具体实例

 

**3、原型模式(克隆模式):**

原型模式:如果某一个类存在大量的属性,然后又需要大量产生该类的相同或者相似的对象的时候,我们就可以使用克隆模式。克隆就是指以什么东西作为参照,大量产生新的对象。

如果大量的对象在产生的时候,大部分的属性或者绝大多数的属性都一样,而只有少量的属性存在差异时,此时,我们就可以使用原型模式。

JAVA中原型模式,实现方式非常简单:实现Cloneable接口,并重写clone()就可以完成对象的“浅克隆”,如果对象的关联对象也需要克隆的话,那么就需要关联对象也要实现实现Cloneable接口,并重写clone(),并且对象克隆时,还要通知关联对象也去克隆,从而做到“深度克隆”。

例子:

 @Override
	public Object clone() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		//加了下面这句话,就叫深度克隆
		this.setWife((Wife)wife.clone());
		return super.clone();
	}

 

**4、单例模式:**

单例模式:如果碰到某种业务场景,如果一个类在整个软件范围内,都只需要拥有1个实例的时候,我们就可以使用单例模式。

例如:多台电脑,对应1台打印机,那么打印机在局域网范围内,就只有1个单实例

 

单实例的实现方式

懒汉式:

  /**
	 * 懒汉,线程不安全版 1.0版本
	 * @return
	 */
	public static RandomSingleton getInstance() {
		if (instance == null) {
			instance = new RandomSingleton();
		}
		return instance;
	}
/**
	 * 懒汉,线程安全版2.0版本
	 * @return
	 */
	public static RandomSingleton getInstance() {
		synchronized (instance) {
			if (instance == null) {
				instance = new RandomSingleton();
			}
			return instance;
		}
	}
/**
	 * 懒汉,线程安全版2.2版本
	 * 双重检测机制
	 * @return
	 */
	public static LazyManSingleton getInstance() {
		if (instance == null) {
			//1,2,3,4……所有的线程
			synchronized (LazyManSingleton.class) {
				
				if(instance == null) {
					instance = new LazyManSingleton();
				}
				
			}
		}
		return instance;
	}


饿汉式:   

/**
     * 单例模式(饿汉式)
     * @author Administrator
     */
    public class HungryManSingleton {
    
    	private static HungryManSingleton instance = new HungryManSingleton();
    	
    	private HungryManSingleton() {
    		// TODO Auto-generated constructor stub
    	}
    	
    	/**
    	 * 天生就是线程安全的
    	 * @return
    	 */
    	public static HungryManSingleton getInstance() {
    		return instance;
    	}
    } 

推荐大家,直接使用饿汉式记住:没有痴汉式,饱汉式……

 

**5、适配器模式:**

当两个类 ,或者说两个组件需要相互通讯的时候,然后两个类又无法直接交互的情况下,比如:美国教练无法直接指挥外籍球员“何憨锋”时,“何憨锋”听不懂英文,那么此时就需要一个适配器|翻译员,来帮我们做一个中间翻译,或者适配的工作!

 

**6、观察者模式:**  

比如:大家在上高中的时候,一大帮观察老师的情况          

比如:商家的货品在降价时,自动通知所有关注该商品的用户

 

观察者模式,定义了一种1对多的依赖关系,让多个观察者对象同时监听|观察同一个主题,当主题的状态发生变化的时候,可以让这些多个观察者自动刷新他们自己。当然这个过程,是由主题来通知观察者发生

如下面这个文件表结构:

observer文件下的Observer抽象类(观察者)、Subject抽象类(被观察者)、MainEnter是测试用的;

impl子文件下的Teacher类(被观察者)继承了Subject抽象类(被观察者),PlayGameStudent、ReadNovelStudent、SeePhoneStudent是继承了Observer抽象类(观察者);

 

在上面中,老师是被观察者,同学们是观察者。

老师类中有个状态属性,当被观察者老师的状态改变后,需要通过老师类中的告知方法,去告知同学自己的状态发生了改变,然后同学去执行相应动作。

在老师类中有个集合用于装下所有不同的同学;

再告知方法中,通过判断老师目前的状态,然后在状态特定的情况下才去执行同学带有的方法,比如看小说等等,同学们的这些行为都是继承于他们的抽象类,只是不同的实现。通过foreach循环方法就可把集合中的同学得到,然后执行同学类的方法。

 

**7、代理模式**

代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。

举个例子来说明:假如说我现在想买一辆二手车,虽然我可以自己去找车源,做质量检测等一系列的车辆过户流程,但是这确实太浪费我得时间和精力了。我只是想买一辆车而已为什么我还要额外做这么多事呢?于是我就通过中介公司来买车,他们来给我找车源,帮我办理车辆过户流程,我只是负责选择自己喜欢的车,然后付钱就可以了。用图表示如下:

为什么要用代理模式?

中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。

开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。

有哪几种代理模式?

       我们有多种不同的方式来实现代理。如果按照代理创建的时期来进行分类的话, 可以分为两种:静态代理、动态代理。静态代理是由程序员创建或特定工具自动生成源代码,在对其编译。在程序员运行之前,代理类.class文件就已经被创建了。动态代理是在程序运行时通过反射机制动态创建的。

 

**8、备忘录模式**

如果某一天,我们存在需要对某一个对象的状态进行备份的时候,我们就可以去使用“备忘录模式”,备忘录模式,要求在不破坏原有对象的封装的基础上,让另外一个对象去记录原对象的所有状态,如果某一天,原对象的状态存在丢失的情况,需要还原时,我们就可以采用另外的对象来进行还原。

备忘录模式中,存在以下角色:

原对象:它是备份数据的发起者
备忘录对象:记录原对象的数据
备忘录管理者对象:管理备忘录对象

 

**9、建造者模式**

当生产的产品,具有固定的建造步骤时,就需要大家去使用建造者模式,建造者模式的主要作用:是将对象的生产与对象的行为表现分离,无论你产生的是什么类型的产品,反正在建造类中都是使用的固定的建造的步骤。建造者模式更多的是用于:封装某一个具有多个组件组成的产品,比如:电脑,汽车,机器人……

你在生产具有多个组件的产品时,又不想让其他人知道你详细的建造过程时,你就可以用建造者模式。

 

**10、装饰器模式**

当需要给某一个对象,动态添加更多的责任的时候,我们就可以使用装饰器模式,比如:给小峰峰穿衣服

装饰的时候,是一层层的装饰,比如:

//要给小峰峰穿衣服,装扮
tx.decorate(person);
ld.decorate(tx);
dk.decorate(ld);
htg.decorate(dk);

**11、责任链模式**

使用场景,稍微要多一些,一般发生在公司具有审批流程时,根据输入的请求条件,来动态的决定由哪一个上级来处理该请求。如果领导没有权利处理请求的话,可以直接抛给上级,让上级接着处理。

责任链模式中:一定要确定好上下级关系,以及每一个领导自身所具备的权利大小。

 

**12、抽象工厂模式**

使用场景:现在系统中,存在多套系列的产品,比如:即存在mysql数据库的产品,又存在SQLServer数据库的产品,那么如果做到2套产品之后,可以动态切换,那么就需要使用到“抽象工厂模式”。

 

猜你喜欢

转载自blog.csdn.net/IT_CREATE/article/details/83929987