JAVA设计模式简介及⼋种常见设计模式详解
⼀、什么是设计模式
  设计模式(Design pattern)是⼀套被反复使⽤、多数⼈知晓的、经过分类编⽬的、代码设计经验的总结。使⽤设计模式是为了可重⽤代码、让代码更容易被他⼈理解、保证代码可靠性。毫⽆疑问,设计模式于⼰于他⼈于系统都是多赢的,设计模式使代码编制真正⼯程化,设计模式是软件⼯程的基⽯,如同⼤厦的⼀块块砖⽯⼀样。项⽬中合理的运⽤设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每⼀个模式描述了⼀个在我们周围不断重复发⽣的问题,以及该问题的核⼼解决⽅案,这也是它能被⼴泛应⽤的原因。简单说:
  模式:在某些场景下,针对某类问题的某种通⽤的解决⽅案。
  场景:项⽬所在的环境
  问题:约束条件,项⽬⽬标等
  解决⽅案:通⽤、可复⽤的设计,解决约束达到⽬标。
⼆、设计模式的六⼤原则
  因为设计模式就是基于这些原则的实现,所以很有必要了解这些原则,下⾯主要对⾯向对象编程的⼏个原则进⾏简单介绍。
  1、开闭原则(Open Close Principle)
  开闭原则就是说对扩展开放,对修改关闭。在程序需要进⾏拓展的时候,不能去修改原有的代码,实现⼀个热插拔的效果。所以⼀句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使⽤接⼝和抽象类,后⾯的具体设计中我们会提到这点。
  2、⾥⽒代换原则(Liskov Substitution Principle)
  ⾥⽒代换原则(Liskov Substitution Principle LSP)⾯向对象设计的基本原则之⼀。⾥⽒代换原则中说,任何基类可以出现的地⽅,⼦类⼀定可以出现。 LSP是继承复⽤的基⽯,只有当衍⽣类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复⽤,⽽衍⽣类也能够在基类的基础上增加新的⾏为。⾥⽒代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。⽽基类与⼦类的继承关系就是抽象化的具体实现,所以⾥⽒代换原则是对实现抽象化的具体步骤的规范。
  3、依赖倒转原则(Dependence Inversion Principle)
  这个是开闭原则的基础,具体内容:真对接⼝编程,依赖于抽象⽽不依赖于具体。
  4、接⼝隔离原则(Interface Segregation Principle)
  这个原则的意思是:使⽤多个隔离的接⼝,⽐使⽤单个接⼝要好。还是⼀个降低类之间的耦合度的意思,从这⼉我们看出,其实设计模式就是⼀个软件的设计思想,从⼤型软件架构出发,为了升级和维护⽅便。所以上⽂中多次出现:降低依赖,降低耦合。
  5、迪⽶特法则(最少知道原则)(Demeter Principle)
  为什么叫最少知道原则,就是说:⼀个实体应当尽量少的与其他实体之间发⽣相互作⽤,使得系统功能模块相对独⽴。
  6、合成复⽤原则(Composite Reuse Principle)
  原则是尽量使⽤合成/聚合的⽅式,⽽不是使⽤继承。
三、设计模式的三个分类
  创建型模式:对象实例化的模式,创建型模式⽤于解耦对象的实例化过程。
  结构型模式:把类或对象结合在⼀起形成⼀个更⼤的结构。
  ⾏为型模式:类和对象如何交互,及划分责任和算法。
  如下图所⽰:
四、各分类中模式的关键点
  创建型模式
  单例模式:某个类只能有⼀个实例,提供⼀个全局的访问点。
  简单⼯⼚:⼀个⼯⼚类根据传⼊的参量决定创建出那⼀种产品类的实例。
  ⼯⼚⽅法:定义⼀个创建对象的接⼝,让⼦类决定实例化那个类。
  抽象⼯⼚:创建相关或依赖对象的家族,⽽⽆需明确指定具体类。
  建造者模式:封装⼀个复杂对象的构建过程,并可以按步骤构造。
  原型模式:通过复制现有的实例来创建新的实例。
  结构性模式
  适配器模式:将⼀个类的⽅法接⼝转换成客户希望的另外⼀个接⼝。
  组合模式:将对象组合成树形结构以表⽰“”部分-整体“”的层次结构。
  装饰模式:动态的给对象添加新的功能。
  代理模式:为其他对象提供⼀个代理以便控制这个对象的访问。
  亨元(蝇量)模式:通过共享技术来有效的⽀持⼤量细粒度的对象。
  外观模式:对外提供⼀个统⼀的⽅法,来访问⼦系统中的⼀接⼝。
  桥接模式:将抽象部分和它的实现部分分离,使它们都可以独⽴的变化。
  ⾏为型模式
  模板模式:定义⼀个算法结构,⽽将⼀些步骤延迟到⼦类实现。
  解释器模式:给定⼀个语⾔,定义它的⽂法的⼀种表⽰,并定义⼀个解释器。
  策略模式:定义⼀系列算法,把他们封装起来,并且使它们可以相互替换。
  状态模式:允许⼀个对象在其对象内部状态改变时改变它的⾏为。
  观察者模式:对象间的⼀对多的依赖关系。
  备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
  中介者模式:⽤⼀个中介对象来封装⼀系列的对象交互。
  命令模式:将命令请求封装为⼀个对象,使得可以⽤不同的请求来进⾏参数化。
  访问者模式:在不改变数据结构的前提下,增加作⽤于⼀组对象元素的新功能。
  责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
  迭代器模式:⼀种遍历访问聚合对象中各个元素的⽅法,不暴露该对象的内部结构。
五、⼋种常见设计模式详解
  1、单例模式
  所谓的单例设计指的是⼀个类只允许产⽣⼀个实例化对象。
  最好理解的⼀种设计模式,分为懒汉式和饿汉式。
  1.1、饿汉式
  ——构造⽅法私有化,外部⽆法产⽣新的实例化对象,只能通过static⽅法取得实例化对象
class Singleton {
/**
* 在类的内部可以访问私有结构,所以可以在类的内部产⽣实例化对象
*/
private static Singleton instance = new Singleton();
/**
* private 声明构造
*/
private Singleton() {
}
/**
* 返回对象实例
*/
public static Singleton getInstance() {
return instance;
}
public void print() {
System.out.println("");
}
}
  1.2、懒汉式
  ——当第⼀次去使⽤Singleton对象的时候才会为其产⽣实例化对象的操作
class Singleton {
/**
* 声明变量
*/
private static volatile Singleton singleton = null;
/**
* 私有构造⽅法
*/
private Singleton() {
}
/**
* 提供对外⽅法
* @return
*/
public static Singleton getInstance() {
// 还未实例化
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
public void print() {
System.out.println("Hello World");
}
}
  当多个线程并发执⾏ getInstance ⽅法时,懒汉式会存在线程安全问题,所以⽤到了 synchronized 来实现线程的同步,当⼀个线程获得锁的时候其他线程就只能在外等待其执⾏完
毕。⽽饿汉式则不存在线程安全的问题。
  2、⼯⼚设计模式
  ⼯⼚模式分为⼯⼚⽅法模式和抽象⼯⼚模式。
  ⼯⼚⽅法模式
⼯⼚⽅法模式:
1. ⼯⼚⽅法模式分为三种:普通⼯⼚模式,就是建⽴⼀个⼯⼚类,对实现了同⼀接⼝的⼀些类进⾏实例的创建。
2. 多个⼯⼚⽅法模式,是对普通⼯⼚⽅法模式的改进,在普通⼯⼚⽅法模式中,如果传递的字符串出错,则不能正确创建对象,⽽多个⼯⼚⽅法模式是提供多个⼯⼚⽅法,分别创建对象。
3. 静态⼯⼚⽅法模式,将上⾯的多个⼯⼚⽅法模式⾥的⽅法置为静态的,不需要创建实例,直接调⽤即可。
  2.1、普通⼯⼚模式
  建⽴⼀个⼯⼚类,对实现了同⼀接⼝的⼀些类进⾏实例的创建。
interface Sender {
void Send();
}
class MailSender implements Sender {
@Override
public void Send() {
System.out.println("This is ");
}
}
class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("This is ");
}
}
public class FactoryPattern {
public static void main(String[] args) {
Sender sender = produce("mail");
sender.Send();
}
public static Sender produce(String str) {
if ("mail".equals(str)) {
return new MailSender();
} else if ("sms".equals(str)) {
return new SmsSender();
} else {
System.out.println("输⼊错误...");
return null;
}
}
}
  2.2、多个⼯⼚⽅法模式
  该模式是对普通⼯⼚⽅法模式的改进,在普通⼯⼚⽅法模式中,如果传递的字符串出错,则不能正确创建对象,⽽多个⼯⼚⽅法模式是提供多个⼯⼚⽅法,分别创建对象。interface Sender {
void Send();
}
class MailSender implements Sender {
@Override
public void Send() {
System.out.println("This is ");
}
}
class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("This is ");
}
}
class SendFactory {
public Sender produceMail() {
return new MailSender();
}
public Sender produceSms() {
return new SmsSender();
}
}
public class FactoryPattern {
public static void main(String[] args) {
SendFactory factory = new SendFactory();
Sender sender = factory.produceMail();
sender.Send();
}
}
  2.3、静态⼯⼚⽅法模式
  将上⾯的多个⼯⼚⽅法模式⾥的⽅法置为静态的,不需要创建实例,直接调⽤即可。
interface Sender {
void Send();
}
class MailSender implements Sender {
@Override
public void Send() {
System.out.println("This is ");
}
}
class SmsSender implements Sender {
@Override
public void Send() {
System.out.println("This is ");
}
}
class SendFactory {
public static Sender produceMail() {
return new MailSender();
}
public static Sender produceSms() {
return new SmsSender();
}
}
public class FactoryPattern {
public static void main(String[] args) {
Sender sender = SendFactory.produceMail();
sender.Send();
}
}
  2.4、抽象⼯⼚模式
  ⼯⼚⽅法模式有⼀个问题就是,类的创建依赖⼯⼚类,也就是说,如果想要扩展程序,必须对⼯⼚类进⾏修改,这违背了闭包原则,所以,从设计⾓度考虑,有⼀定的问题,如何解决?
  那么这就⽤到了抽象⼯⼚模式,创建多个⼯⼚类,这样⼀旦需要增加新的功能,直接增加新的⼯⼚类就可以了,不需要修改之前的代码。
interface Provider {
Sender produce();
}
interface Sender {
void Send();
}
class MailSender implements Sender {
public void Send() {
System.out.println("This is ");
}
}
class SmsSender implements Sender {
public void Send() {
System.out.println("This is ");
}
}
class SendMailFactory implements Provider {
public Sender produce() {
return new MailSender();
}
}
class SendSmsFactory implements Provider {
public Sender produce() {
return new SmsSender();
}
}
public class FactoryPattern {
public static void main(String[] args) {
Provider provider = new SendMailFactory();
Sender sender = provider.produce();
sender.Send();
}
}
  3、建造者模式
  ⼯⼚类模式提供的是创建单个类的模式,⽽建造者模式则是将各种产品集中起来管理,⽤来创建复合对象,所谓复合对象就是指某个类具有不同的属性。import java.util.ArrayList;
import java.util.List;
/**
* @Author: LiuWang
* @Created: 2018/8/6 17:47
*/
abstract class Builder {
/**
* 第⼀步:装CPU
*/
public abstract void buildCPU();
/**
* 第⼆步:装主板
*/
public abstract void buildMainBoard();
/**
* 第三步:装硬盘
*/
适配器字符串是什么
public abstract void buildHD();
/**
* 获得组装好的电脑
* @return
*/
public abstract Computer getComputer();
}
/**
* 装机⼈员装机
*/
class Director {
public void Construct(Builder builder) {
builder.buildCPU();
builder.buildMainBoard();
builder.buildHD();
}
}
/**
* 具体的装机⼈员
*/
class ConcreteBuilder extends  Builder {
Computer computer = new Computer();
@Override
public void buildCPU() {
computer.Add("装CPU");
}
@Override
public void buildMainBoard() {
computer.Add("装主板");
}
@Override
public void buildHD() {
computer.Add("装硬盘");
}
@Override
public Computer getComputer() {
return computer;
}
}
class Computer {
/**
* 电脑组件集合
*/
private List<String> parts = new ArrayList<String>();
public void Add(String part) {
parts.add(part);
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。