一、常用设计原则
1、开闭原则:对扩展开放对修改关闭,为了使程序的扩展性好,易于维护和升级。
2、里氏代换原则:任何基类可以出现的地方,子类一定可以出现,多使用多态的方式。
3、依赖倒转原则:尽量多依赖于抽象类或接口而不是具体实现类,对子类具有强制性和规范性
4、接口隔离原则:尽量多使用小接口而不是大接口,避免接口的污染,降低类之间耦合度。
5、迪米特法则(最少知道原则):一个实体应当尽量少与其他实体之间发生相互作用,使系统功能模块相对独立。高内聚,低耦合。
6、合成复用原则:尽量多使用合成/聚合的方式,而不是继承的方式。
二、常用设计模式
基本概念:设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
基本分类:
创建型模式 - 单例设计模式、工厂方法模式、抽象工厂模式、...
结构型模式 - 装饰器模式、代理模式、...
行为型模式 - 模板设计模式、...
1、单列设计模式
①、饿汉式
package com.designpattern;
public class Singleton {
// 1、声明本类类型的引用指向本类类型的对象并使用private static关键字修饰
private static final Singleton instance = new Singleton();
// 2、私有化构造方法,使用private关键字修饰
private Singleton() {}
// 3、静态方法返回该实例
public static Singleton getInstance() {
return instance;
}
}
优点:实现起来简单,没有多线程同步问题。
缺点:当类SingletonTest被加载的时候,会初始化static的instance,静态变量被创建并分配内存空间,从这以后,这个static的instance对象便一直占着这段内存(即便你还没有用到这个实例),当类被卸载时,静态变量被摧毁,并释放所占有的内存,因此在某些特定条件下会耗费内存。
②、懒汉式
package com.designpattern;
/**
* 懒汉式
*/
public class Singleton1 {
// 1、声明本类类型的引用指向本类类型的对象并使用private static关键字修饰
private static Singleton1 sin=null;
// 2、构造方法私有化
private Singleton1() {}
// 3、静态方法返回该实例
public static Singleton1 getSin() {
if(sin == null) {
sin = new Singleton1();
}
return sin;
}
}
优点:实现起来比较简单,当类SingletonTest被加载的时候,静态变量static的sin未被创建并分配内存空间,当getSin方法第一次被调用时,初始化sin变量,并分配内存,因此在某些特定条件下会节约了内存。
缺点:在多线程环境中,这种实现方法是完全错误的,根本不能保证单例的状态,线程不安全。如:当两个线程同时加载getSin方法,前面一个还没有创建完对象的时候,后一个线程进来sin为null,第二个线程会再创建一个对象。
③、线程安全的懒汉式
package com.designpattern;
/**
* 线程安全的懒汉式
*/
public class Singleton2 {
// 1、声明本类类型的引用指向本类类型的对象并使用private static关键字修饰
private static Singleton2 sin = null;
// 2、私有化构造方法,使用private关键字修饰
private Singleton2() {}
// 3、提供公有的get方法负责将上述对象返回出去,使用public static关键字修饰
public static Singleton2 getInstance() {
//4、第一次检查instance是否被实例化出来,如果没有进入if块
if (null == sin) {
//5、获取类锁,实例化对象前第二次检查sin是否已经被实例化出来,如果没有,实例出对象
synchronized (Singleton2.class) {
if (null == sin) {
sin = new Singleton2();
}
}
}
return sin;
}
}
方式③为单例模式的最佳实现方式。内存占用率高,效率高,线程安全
2、工厂设计模式
①、普通工厂模式
类图结构:
发送接口:
package com.designpattern.factorydesign;
public interface Sender {
// 自定义抽象方法来描述发送的行为
void send();
}
具体类 邮件
package com.designpattern.factorydesign;
public class MailSender implements Sender {
@Override
public void send() {
System.out.println("正在发送邮件...");
}
}
具体类 短信
package com.designpattern.factorydesign;
public class SmsSender implements Sender {
@Override
public void send() {
System.out.println("正在发送短信...");
}
}
具体工厂 发送工厂
package com.designpattern.factorydesign;
public class SendFactory {
public Sender produce(String type) {
if ("mail".equals(type)) {
return new MailSender();
}
if ("sms".equals(type)) {
return new SmsSender();
}
return null;
}
}
测试类
package com.designpattern.factorydesign;
public class SendFactoryTest {
public static void main(String[] args) {
SendFactory sf = new SendFactory();
Sender sender = sf.produce("mail");
Sender sender1 = sf.produce("sms");
//发送邮件
sender.send();
//发送短信
sender1.send();
}
}
就这样,一个非常简单的工厂设计模式就完成了,但是有没有发现什么问题呢?
如果我们要发送QQ消息或者微信呢,就必然要修改工厂类,这显然违反了开闭原则,亦不可取;所以简单工厂只适合于产品对象较少,且产品固定的需求,对于产品变化无常的需求来说显然不合适。
②、多个工厂模式
类图
具体类 发送邮件工厂
package com.designpattern.factorydesign;
public class MailSendFactory {
/**
* 发送邮件
* @return
*/
public Sender produceMail() {
return new MailSender();
}
}
具体类 发送短信工厂
package com.designpattern.factorydesign;
public class SmsSendFactory {
/**
* 发送短信
* @return
*/
public Sender produceSms() {
return new SmsSender();
}
}
测试类
package com.designpattern.factorydesign;
public class SendFactoryTest {
public static void main(String[] args) {
MailSendFactory ms=new MailSendFactory();
SmsSendFactory sf=new SmsSendFactory();
Sender sender=ms.produceMail();
Sender sender1=sf.produceSms();
sender.send();
sender1.send();
}
}
以上这种方式,虽然解耦了,也遵循了开闭原则,但是问题根本还是没有解决啊,换汤没换药,如果我需要的产品很多的话,需要创建非常多的工厂,所以这种方式的缺点也很明显。
③、抽象工厂模式
类图
生产接口
package com.designpattern.factorydesign;
public interface Provider {
// 自定义抽象方法描述产品的生产行为
Sender produce();
}
具体实现类 邮件工厂
package com.designpattern.factorydesign;
/**
* 发送邮件
*/
public class MailSendFactory implements Provider {
@Override
public Sender produce() {
return new MailSender();
}
}
具体实现类 短信工厂
package com.designpattern.factorydesign;
public class SmsSendFactory implements Provider{
/**
* 发送短信
* @return
*/
@Override
public Sender produce() {
return new SmsSender();
}
}
测试类
package com.designpattern.factorydesign;
public class SendFactoryTest {
public static void main(String[] args) {
Provider provider1 = new MailSendFactory();
Provider provider2 = new SmsSendFactory();
Sender sender1 = provider1.produce();
Sender sender2 = provider2.produce();
sender1.send();
sender2.send();
}
}
以上例子可以看出,抽象工厂可以解决一系列的产品生产的需求,对于大批量,多系列的品,用抽象工厂可以更好的管理和扩展。
3、装饰器设计模式
类图
被装饰的抽象类:
package com.designpattern.decorator;
public interface Sourceable {
void method();
}
被装饰的具体类:
package com.designpattern.decorator;
public class Source implements Sourceable {
@Override
public void method() {
System.out.println("穿西装!");
}
}
装饰类:
package com.designpattern.decorator;
public class Decorator implements Sourceable {
private Sourceable source;
public Decorator(Sourceable source) {
this.source = source;
}
@Override
public void method() {
source.method(); //保证原有功能不变
System.out.println("打领带!");
}
}
总结:装饰模式在不改变原先核心功能的情况下,可以实现增强,并且不会产生很多继承类。
4、代理设计模式
类图
被代理的接口:
package com.designpattern.decorator;
public interface Sourceable {
void method();
}
被代理的具体类:
package com.designpattern.decorator;
public class Source implements Sourceable {
@Override
public void method() {
System.out.println("穿西装!");
}
}
代理类:
package com.designpattern.decorator;
public class Proxy implements Sourceable {
private Source source;
public Proxy() {
source = new Source();
}
@Override
public void method() {
source.method();
System.out.println("穿短袖!");
}
}
总结:使用代理模式,可以将功能划分的更加清晰,有助于后期维护。
5、模板设计模式
类图:
模板抽象类:
package com.designpattern.template;
public abstract class AbstractCalculator {
// 自定义成员方法实现将参数指定的表达式按照参数指定的规则进行切割并返回计算结果
public int splitExpression(String exp, String op) {
String[] sArr = exp.split(op);
return calculate(Integer.parseInt(sArr[0]), Integer.parseInt(sArr[1]));
}
// 自定义抽象方法实现运算
public abstract int calculate(int ia, int ib);
}
模板实现类1:
package com.designpattern.template;
public class Plus extends AbstractCalculator {
@Override
public int calculate(int ia, int ib) {
return ia + ib;
}
}
模板实现类2:
package com.designpattern.template;
public class Minus extends AbstractCalculator {
@Override
public int calculate(int ia, int ib) {
return ia - ib;
}
}
测试类:
package com.designpattern.template;
public class AbstractCalculatorTest {
public static void main(String[] args) {
AbstractCalculator abstractCalculator = new Plus();
AbstractCalculator abstractCalculator1 = new Minus();
int res = abstractCalculator.splitExpression("1+1", "\\+");
System.out.println("最终的运算结果是:" + res);
int res1 = abstractCalculator1.splitExpression("10-4", "-");
System.out.println("最终的运算结果是:" + res1);
}
}
总结:通过模板设计模式可以让不同的子类实现不同的效果形成多态,有助于后期维护。
下一篇:https://blog.csdn.net/qq_42068838/article/details/118311919