0
点赞
收藏
分享

微信扫一扫

【卡卡谈Java】Java 设计模式

梦为马 2022-02-19 阅读 21

Java 设计模式


  同学们,今天我们来一起学习Java中的设计模式,学习好设计模式会是我们在日常的开发中会方便很多,让自己写的代码容易让别人理解。

设计模式概念

  Java设计模式是一种反复使用的代码设计总结,设计模式的目的是重用代码、让代码容易被他人所理解、同时也保证了代码的可靠稳定性。在日常的项目开发中,合理的使用设计模式可以完美的解决对应的问题。

设计模式分类

  • 建造者模型(5种)
  • 结构型模式(7种)
  • 行为型模式(11种)

设计模式的六大原则

1)开闭原则
  开闭原则指的是对扩展开放,对修改关闭。在对程序进行扩展的时候,不能去修改原有的代码,想要达到这样的效果,我们就需要使用接口或者抽象类
2) 依赖倒转原则
   依赖倒置原则是开闭原则的基础,指的是针对接口编程,依赖于抽象而不依赖于具体
3) 里氏替换原则
  里氏替换原则是继承与复用的基石,只有当子类可以替换掉基类,且系统的功能不受影响时,基类才能被复用,而子类也能够在基础类上增加新的行为。所以里氏替换原则指的是任何基类可以出现的地方,子类一定可以出现。
  里氏替换原则是对 “开闭原则” 的补充,实现 “开闭原则” 的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏替换原则是对实现抽象化的具体步骤的规范。
4)接口隔离原则
  使用多个隔离的接口,比使用单个接口要好,降低接口之间的耦合度与依赖,方便升级和维护方便
5)迪米特原则
  迪米特原则,也叫最少知道原则,指的是一个类应当尽量减少与其他实体进行相互作用,使得系统功能模块相对独立,降低耦合关系。该原则的初衷是降低类的耦合,虽然可以避免与非直接的类通信,但是要通信,就必然会通过一个“中介”来发生关系,过分的使用迪米特原则,会产生大量的中介和传递类,导致系统复杂度变大,所以采用迪米特法则时要反复权衡,既要做到结构清晰,又要高内聚低耦合。
6)合成复用原则
  尽量使用组合/聚合的方式,而不是使用继承。

Java 常见的模式

这里我们只介绍几种设计模式的使用,这些一般在日常开发当中,是够使用的。

单例设计模式

所谓单例设计模式简单说就是无论程序如何运行,采用单例设计模式的类(Singleton类)永远只会有一个实例化对象产生。具体实现步骤如下:

  • 将采用单例设计模式的类的构造方法私有化(采用private修饰)。
  • 在其内部产生该类的实例化对象,并将其封装成private static类型。
  • 定义一个静态方法返回该类的实例。

示例代码如下所示:

class Singleton {
	private static Singleton instance = new Singleton();// 在内部产生本类的实例化对象
 
	public static Singleton getInstance() { // 通过静态方法返回instance对象
		return instance;
	}
 
	private Singleton() { // 将构造方法封装为私有化
	}
 
	public void print() {
		System.out.println("Hello World!!!");
	}
}
 
public class SingletonDemo {
	public static void main(String args[]) {
		Singleton s1 = null; // 声明对象
		Singleton s2 = null; // 声明对象
		Singleton s3 = null; // 声明对象
		s1 = Singleton.getInstance(); // 取得实例化对象
		s2 = Singleton.getInstance(); // 取得实例化对象
		s3 = Singleton.getInstance(); // 取得实例化对象
		s1.print(); // 调用方法
		s2.print(); // 调用方法
		s3.print(); // 调用方法
	}
}

单例模式介绍

  Singleton是一种创建型模式,指某个类采用Singleton模式,则在这个类被创建后,只可能产生一个实例供外部访问,并且提供一个全局的访问点

单例模式实现

单例模式总共有四种实现方式:

  • 饿汉式,线程安全 但效率比较低
/**
 * 
 * 单例模式的实现:饿汉式,线程安全 但效率比较低
 */
public class SingletonTest {
 
	private SingletonTest() {
	}
 
	private static final SingletonTest instance = new SingletonTest();
 
	public static SingletonTest getInstancei() {
		return instance;
	}
 
}
  • 单例模式的实现:饱汉式,非线程安全
/**
 * 单例模式的实现:饱汉式,非线程安全 
 * 
 */
public class SingletonTest {
	private SingletonTest() {
	}
 
	private static SingletonTest instance;
 
	public static SingletonTest getInstance() {
		if (instance == null)
			instance = new SingletonTest();
		return instance;
	}
}
  • 线程安全,但是效率非常低
/**
 * 线程安全,但是效率非常低
 * @author vanceinfo
 *
 */
public class SingletonTest {
	private SingletonTest() {
	}
 
	private static SingletonTest instance;
 
	public static synchronized SingletonTest getInstance() {
		if (instance == null)
			instance = new SingletonTest();
		return instance;
	}
}
  • 线程安全,效率非常高
/**  
 * 线程安全  并且效率高  
 *  
 */  
public class SingletonTest {   
    private static SingletonTest instance;   
  
    private SingletonTest() {   
    }   
  
    public static SingletonTest getIstance() {   
        if (instance == null) {   
            synchronized (SingletonTest.class) {   
                if (instance == null) {   
                    instance = new SingletonTest();   
                }   
            }   
        }   
        return instance;   
    }   
}  

工厂模式详解(简单工厂+工厂方法+抽象工厂)

  工厂模式将目的将创建对象的具体过程屏蔽隔离起来,从而达到更高的灵活性,工厂模式可以分为三类:

  • 简单工厂模式(Simple Factory)
  • 工厂方法模式(Factory Method)
  • 抽象工厂模式(Abstract Factory)

简单工厂模式

  简单工厂模式的核心是定义一个创建对象的接口,将对象的创建和本身的业务逻辑分离,降低系统的耦合度,使得两个修改起来相对容易些,当以后实现改变时,只需要修改工厂类即可。

  1. 简单工厂的UML图
    简单工厂的UML图
  1. 代码实现
    产品类:
abstract class BMW {
	public BMW(){}
}
 
public class BMW320 extends BMW {
	public BMW320() {
		System.out.println("制造-->BMW320");
	}
}
public class BMW523 extends BMW{
	public BMW523(){
		System.out.println("制造-->BMW523");
	}
}

工厂类:

public class Factory {
	public BMW createBMW(int type) {
		switch (type) {
		
		case 320:
			return new BMW320();
 
		case 523:
			return new BMW523();
 
		default:
			break;
		}
		return null;
	}
}

用户类:

public class Customer {
	public static void main(String[] args) {
		Factory factory = new Factory();
		BMW bmw320 = factory.createBMW(320);
		BMW bmw523 = factory.createBMW(523);
	}
}
  1. 简单工厂模式总结
      简单工厂模式提供专门的工厂类用于创建对象,实现了对象创建和使用的职责分离,客户端不需知道所创建的具体产品类的类名以及创建过程,只需知道具体产品类所对应的参数即可,通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
      但缺点在于不符合“开闭原则”,每次添加新产品就需要修改工厂类。在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展维护,并且工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。
      为了解决简单工厂模式的问题,出现了工厂方法模式。

工厂方法模式

  程序接口和子类之间加入工厂方法模式将工厂抽象化,并定义一个创建对象的接口。每增加新产品,只需增加该产品以及对应的具体实现工厂类,由具体工厂类决定要实例化的产品是哪个,将对象的创建与实例化延迟到子类,这样工厂的设计就符合“开闭原则”了,扩展时不必去修改原来的代码。在使用时,用于只需知道产品对应的具体工厂,关注具体的创建过程,甚至不需要知道具体产品类的类名,当我们选择哪个具体工厂时,就已经决定了实际创建的产品是哪个了。
  但缺点在于,每增加一个产品都需要增加一个具体产品类和实现工厂类,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
代码实现如下:
产品类:

abstract class BMW {
	public BMW(){}
}
public class BMW320 extends BMW {
	public BMW320() {
		System.out.println("制造-->BMW320");
	}
}
public class BMW523 extends BMW{
	public BMW523(){
		System.out.println("制造-->BMW523");
	}
}

工厂类:

interface FactoryBMW {
	BMW createBMW();
}
 
public class FactoryBMW320 implements FactoryBMW{
 
	@Override
	public BMW320 createBMW() {
		return new BMW320();
	}
 
}
public class FactoryBMW523 implements FactoryBMW {
	@Override
	public BMW523 createBMW() {
		return new BMW523();
	}
}

客户类:

public class Customer {
	public static void main(String[] args) {
		FactoryBMW320 factoryBMW320 = new FactoryBMW320();
		BMW320 bmw320 = factoryBMW320.createBMW();
 
		FactoryBMW523 factoryBMW523 = new FactoryBMW523();
		BMW523 bmw523 = factoryBMW523.createBMW();
	}
}

抽象工厂模式

  工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题,如何解决?就用到抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。因为抽象工厂不太好理解,我们先看看图,然后就和代码,就比较容易理解。
抽象工厂模式
示例代码如此下:

public interface Sender {
	public void Send();
}

两个实现类:

public class MailSender implements Sender {
	@Override
	public void Send() {
		System.out.println("this is mailsender!");
	}
}
public class MailSender implements Sender {
	@Override
	public void Send() {
		System.out.println("this is mailsender!");
	}
}

再提供一个接口:

public interface Provider {
	public Sender produce();
}

两个工厂类:

    public class SendMailFactory implements Provider {
    	
    	@Override
    	public Sender produce(){
    		return new MailSender();
    	}
    }
public class SendSmsFactory implements Provider{
 
	@Override
	public Sender produce() {
		return new SmsSender();
	}
}

测试类:

public class Test {
 
	public static void main(String[] args) {
		Provider provider = new SendMailFactory();
		Sender sender = provider.produce();
		sender.Send();
	}
}

代理设计模式

  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。简单的说就是,我们在访问实际对象时,是通过代理对象来访问的,代理模式就是在访问实际对象时引入一定程度的间接性,因为这种间接性,可以附加多种用途
示例代码如下:

interface Network { // 定义Network接口
	public void browse(); // 定义浏览的抽象方法
}
 
class Real implements Network { // 真实的上网操作
	public void browse() { // 覆写抽象方法
		System.out.println("上网浏览信息!");
	}
}
 
class Proxy implements Network { // 代理上网
	private Network network;
 
	public Proxy(Network network) {// 设置代理的真实操作
		this.network = network; // 设置代理的子类
	}
 
	public void check() { // 身份验证操作
		System.out.println("检查用户是否合法!");
	}
 
	public void browse() {
		this.check(); // 调用具体的代理业务操作
		this.network.browse(); // 调用真实的上网操作
	}
}
 
public class ProxyDemo {
	public static void main(String args[]) {
		Network net = null; // 定义接口对象
		net = new Proxy(new Real()); // 实例化代理,同时传入代理的真实操作
		net.browse(); // 调用代理的上网操作
	}
}
## 结语
  以上就是卡卡今日分享的Java 设计模式的主要内容,如果有写错的地方,希望同学们踊跃在评论区指出来,欢迎大家一起分享学习。
举报

相关推荐

0 条评论