18.设计模式
本章目标
- 简介
- 工厂模式
- 单例模式
本章内容
一、简介
1、什么是设计模式
设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
- 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
- 每个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。
- 设计模式的贯穿思想:针对接口编程,最大限度的适应变化,实现代码重用
2、设计模式基本要素
- 模式名称(pattern name):一个助记名, 它用一两个词来描述模式的问题、解决方案和效果。
- 问题(problem):描述了应该在何时使用模式它解释了设计问题和问题存在的前因后果,它可能描述了特定的设计问题,如怎样用对象表示算法等。
- 解决方案(solution):描述了设计的组成成分,它们之间的相互关系及各自的职责和协作方式。
- 效果(consequences) : 描述了模式应用的效果及使用模式应权衡的问题。
3、设计模式的分类
我们根据两条准则对模式进行分类。
3.1、第一是目的准则
即模式是用来完成什么工作的
模式依据其目的可分为:
- 创建型(Creational) 创建型模式与对象的创建有关
- 结构型 (Structural) 结构型模式处理类或对象的组合
- 行为型(Behavioral) 行为型模式对类或对象怎样交互和怎样分配职责进行描述
3.2、第二是范围准则
指定模式主要是用于类还是用于对象。
- 类模式:处理类和子类之间的关系,这些关系通过继承建立,是静态的,在编译时刻便确定下来了。
- 对象模式:处理对象间的关系,这些关系在运行时刻是可以变化的,更具动态性。
从某种意义上来说,几乎所有模式都使用继承机制,所以“类模式”只指那些集中于处理类间关系的模式,而大部分模式都属于对象模式的范畴
3.3、创建模式
创建模式(Creational Pattern):是对类的实例化过程的抽象化
一些系统在创建对象时,需要动态地决定怎样创建对象、创建哪些对象,创建模式描述了怎样构造和封装这些动态的决定:
- 工厂方法(Factory Method)
- 抽象工厂(Abstract Factory)
- 单例(Singletion)
- 原型(Prototype)
- 建造者(Builder)
3.4、结构模式
结构模式(Structural Pattern):描述如何将类或者对象结合在一起形成更大的结构,结构模式描述了两种不同的东西:类、类的实例
- 适配器(Adapter)
- 桥接(Bridge)
- 组合(Composite)
- 装饰(Decorator)
- 外观(Facade)
- 享元(Flyweight)
- 代理(Proxy)
3.5、行为模式
在不同的对象之间划分责任和算法,而且解决对象之间如何相互作用
- 迭代(Iterator)
- 模板方法(Template Method)
- 职责链(Chain of Responsibility)
- 访问者(Visitor)
- 中介者(Mediator)
- 观察者(Observer)
- 备忘录(Memento)
- 状态(State)
- 策略(Strategy)
- 命令(Command)
- 解释器(Interpreter)
二、工厂模式
1、概念
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
工厂模式又叫静态工厂方法模式、简单工厂
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象
2、结构
模式的核心是工厂类。这个类含有必要的判断逻辑,可以决定在什么时候创建那一个产品类的实例。而客户端则可以免除直接创建产品对象的责任,而仅仅负责“消费”产品。简单工厂模式通过这种做法实现了对责任的分割
- 工厂类(Creator)角色:担任这个角色的是工厂模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象,它往往由一个具体Java类实现。
- 抽象产品(Product)角色:担任这个角色的类是由工厂方法模式所创建的对象的父类,或它们共同拥有的接口。抽象产品角色可以用一个Java接口或者java抽象类实现。
- 具体产品(Concrete Product)角色:工厂方法模式所创建的任何对象都是这个角色的实例,具体产品角色有一个具体java类实现
3、创建测试接口及实现类
-
IFruit接口
package com.woniuxy.service; public interface IFruit { public void eat(); }
-
Apple实现类
package com.woniuxy.service.impl; import com.woniuxy.service.IFruit; public class Apple implements IFruit { @Override public void eat() { System.out.println("eat Apple"); } }
其它实现Banana,Orange类和该实现结构相同
4、创建工厂类
创建工厂类
public class FruitFactory {
public static IFruit getFruit(String type) {
switch(type){
case "Apple":
return new Apple();
break;
case "Orange":
return new Orange();
break;
case "Banana":
return new Banana();
break;
}
return null;
}
}
调用:
IFruit fruit = FruitFactory.getFruit("Apple");
fruit.eat()
5、优化工厂模式
public class FruitFactory {
public static IFruit getFruit(String type) {
IFruit fruit=null;
try {
fruit=(IFruit)Class.forName("com.woniuxy.factory."+type).newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return fruit;
}
}
三、单例(Singleton)模式
1、概念
单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
这里有三个要点:
- 某个类只能有一个实例
- 类必须自行创建这个实例
- 以公共、统一的方式向整个系统提供这个实例
2、应用场景
许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。
比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。
这种方式简化了在复杂环境下的配置管理。
Java中JDBC的DataSoucre只需要一个实例,但是如果我们想创建多个实例语法上是没有问题的(虽然会造成代码的冗余)。
因此单例模式本质上就是:借助编程语言自身的语法特性,强制限制某个类,不能创建多个实例。
3、分类
单例模式常用分类有两种:
- 饿汉式
- 懒汉式
4、饿汉式
直接创建对象
/**
* 饿汉式
* @author 冯Sir
*
*/
public class EagerSingleton {
private static final EagerSingleton m_instance = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
return m_instance;
}
}
5、懒汉式
先判断,再创建对象
/**
* 懒汉式
* @author 冯Sir
*
*/
public class LazySingleton {
private static LazySingleton m_instance = null;
private LazySingleton() {
}
public static LazySingleton getInstance() {
if (m_instance == null) {
m_instance = new LazySingleton();
}
return m_instance;
}
}
四、Prototype模式
1、概念
Prototype模式即原型模式,原型模式其实是一个比较单纯的设计模式,其目的就是利用一个原型对象,快速地生成一批对象,从而避免重复的新建过程。
工作原理是:通过将一个原型对象传给一个要新建的对象,新建对象通过请求原型对象拷贝它们,然后自己来实施创建
2、适应场景
主要适用于以下情况:
- 构建函数相对比较复杂
- 构建函数不能被不相关的人调用
- 一批对象中绝大部分对象的属性一致,而只有极少数不同
3、结构图
- Prototype:声明一个克隆自身的接口或抽象类
- ConcretePrototype:实现一个克隆自身的操作
- Client:让一个原型来克隆自身从而创建一个新的对象
4、代码实现
-
创建Prototype类
package com.it.demo.prototype; public abstract class Prototype implements Cloneable{ public Prototype clone() throws CloneNotSupportedException { return (Prototype) super.clone(); } public abstract void setId(String id); }
-
创建ConcretrPrototype
package com.it.demo.prototype; public class Student extends Prototype { private String stuName; private float chiness; private float english; private float maths; private float moral; public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } public float getChiness() { return chiness; } public void setChiness(float chiness) { this.chiness = chiness; } public float getEnglish() { return english; } public void setEnglish(float english) { this.english = english; } public float getMaths() { return maths; } public void setMaths(float maths) { this.maths = maths; } public float getMoral() { return moral; } public void setMoral(float moral) { this.moral = moral; } public String toString() { return “[” + this.stuName + “]” + this.chiness + “ + this.english +” + this.maths + “ + this.moral; } public void setId(String id) { this.stuName = id; } }
-
School
package com.it.demo.prototype; public class School { public void showOther(Prototype pro) { try { Prototype other = pro.clone(); other.setId(“sun liang”); System.out.println(other); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } public static void main(String[] args) { Student goodStu = new Student(); goodStu.setChiness(80); goodStu.setEnglish(85); goodStu.setMaths(90); goodStu.setMoral(99); School sch = new School(); sch.showOther(goodStu); } }
思维导图
本文来自博客园,作者:icui4cu,转载请注明原文链接:https://www.cnblogs.com/icui4cu/p/18816530