设计模式
高内聚、低耦合、可扩展、可复用 。
遵循六大原则:
单一职责(一个类和方法只做一件事 )、
里氏替换( 多态,子类可扩展父类 )、
依赖倒置( 细节依赖抽象,下层依赖上层 )、
接口隔离( 建立单一接口 )、
迪米特原则( 最少知道,降低耦合 )、
开闭原则( 抽象架构,扩展实现 )
创建型模式
这类模式提供创建对象的机制, 能够提升已有代码的灵活性和可复用性。
工厂模式
在父类中提供一个创建对象的方法, 允许子类决定实例例化对象的类型。
主要意图是定义一个创建对象的接口,让其子类自己决定实例化对象的类型。
为了提供代码结构的扩展性,屏蔽每一个功能类中的具体实现逻辑。让外部可以更简单的只知道调用即可。
- 实例:发奖
1.定义发奖接口
2.针对不同的发奖类型,实现不同的发奖模式
3.定义商店工厂,这里是有if判断类型,返回不同的实现
工厂模式优点:
- 避免创建者与具体的产品逻辑耦合,
- 满足单一职责,每一个业务逻辑实现都在所属自己的类中完成
- 满足开闭原则,无需更改使用调用方法就可以在程序中引入新的产品类型。
抽象工厂模式
抽象工厂是一个中心工厂,创建其他工厂的模式。
- 例子:redis 升级
抽象工厂的创建和获取方式,会采用代理类的方式进行实现。
CacheService proxy_EGM = JDKProxy.getProxy(CacheServiceImpl.class, new jvaaEGMCacheAdapter());
核心代码:
1. ICacheAdapter:
2. JDKProxy,JDKInvocationHandler:
总结:
抽象工厂模式,所要解决的问题就是在一个产品族,存在多个不同类型的产品情况下,接口选择的问题。
抽象工厂设计模式满足了:单一职责,开闭原则,解耦等优点。但随着业务的不断扩展,可能会造成类实现上的复杂度。但可以随着其他设计方式的引入和代理类以及自动生成加载的方式降低此项缺点。
建造者模式
建造者模式所完成的内容就是通过将多个简单对象通过一步步的组装构建出一个复杂对象的过程。
建造者模式的最终意图,也就是;
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
建造者模式主要解决的问题是在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的过程构成;由于需求的变化,这个复杂对象的各个部分经常面临着重大的变化,但是将它们组合在一起的过程却相对稳定。
- 例子:装修公司
对于建造者模式:使用场景,当一些基本物料不会变,而其组合经常变化的时候,可以使用。
核心类:
1. builder,建造者类具体的各种组装由此类实现 。
2. DecorationPackageMenu,是 IMenu 接口的实现类,主要是承载建造过程中的填充器器。
建造者模式满足了:1.单一职责原则 2. 可复用的技术。建造者模式独立,易扩展,便于控制细节风险。这种设计结构模型可以把重复的内容抽象到数据库中,按照需要配置。这样就可以减少代码中大量量的重复。
原型模式
原型模式主要解决的问题就是创建重复对象,而这部分对象内容本身比较复杂,生成过程可能从库或者RPC接口中获取数据的耗时较长,因此采用克隆的方式节省时间。
在原型模式中所需要的非常重要的手段就是克隆,在需要用到克隆的类中都需要实现 implements Cloneable 接口。
原型模式
在开发中重构的作用 。
原型设计模式的优点:
- 便于通过克隆方式创建复杂对象。
- 避免重复做初始化操作。
- 不需要与类中所属的其他类耦合等。
缺点:如果对象中包括了循环引用的克隆,以及类中深度使用对象的克隆,都会使此模式变得异常麻烦。
单列模式
在编程开发中,需要保证一个类只有一个实例哪怕多线程同时访问,并需要提供一个全局访问此实例的点。
单例例模式主要解决的是,一个全局使用的类频繁的创建和消费,从而提升提升整体的代码的性能。
-
七种单例模式实现
-
静态类使用:定义静态类,在不需要维持任何状态下,仅仅用于全局访问,这个使用静态类的方式更加方便。
-
懒汉模式(非线程安全):单例模式特点,不允许外部直接创建。
// 多线程下,此方法是不安全的。 public class Singleton_01 { private static Singleton_01 instance; private Singleton_01() { } public static Singleton_01 getInstance(){ if (null != instance) return instance; instance = new Singleton_01(); return instance; } }
-
懒汉模式(线程安全)
// 把锁加到方法上后,所有的访问都因需要锁占用导致资源的浪费。 public class Singleton_02 { private static Singleton_02 instance; private Singleton_02() { } public static synchronized Singleton_02 getInstance(){ if (null != instance) return instance; instance = new Singleton_02(); return instance; } }
-
饿汉模式(线程安全)
// 非懒加载 public class Singleton_03 { private static Singleton_03 instance = new Singleton_03(); private Singleton_03() { } public static Singleton_03 getInstance() { return instance; } }
-
使用类的内部类(线程安全)
// 推荐使用 public class Singleton_04 { private static class SingletonHolder { private static Singleton_04 instance = new Singleton_04(); } private Singleton_04() { } public static Singleton_04 getInstance() { return SingletonHolder.instance; } }
-
双重锁校验(线程安全)
public class Singleton_05 { private static Singleton_05 instance; private Singleton_05() { } public static Singleton_05 getInstance(){ if(null != instance) return instance; synchronized (Singleton_05.class){ if (null == instance){ instance = new Singleton_05(); } } return instance; } }
-
CAS(线程安全)
// CAS 忙等算法,依赖底层硬件的实现,来保证线程安全。
-
Effective Java 作者推荐:枚举单列(线程安全)
// 这种方式解决了了最主要的;线程安全、自由串行化、单一实例。 public enum Singleton_07 { INSTANCE; public void test(){ System.out.println("hi~"); } } @Test public void test() { Singleton_07.INSTANCE.test(); }
-
平时的开发中如果可以确保此类是全局可用不需要做懒加载,那么直接创建并给外部调用即可。但如果是很多的类,有些需要在用户触发一定的条件后才显示,那么一定要用懒加载。线程的安全上可以按需选择。