迪米特法则:Law of Demeter, LoD, 最少知识原则LKP
如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。
所以,在运用迪米特法则时要注意以下 6 点。
创建型模式:工厂模式、抽象工厂模式、生成器模式、原型模式、单例模式
结构型模式:适配器、桥接、组合、装饰器、外观、享元、代理
要求一个类有且仅有一个实例,并提供了一个全局的访问点,在同一时刻只能被一个线程所访问。
特点:
https://www.cnblogs.com/libingql/archive/2012/12/01/2797532.html
实现要点:
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 AtomicReference(线程安全)
枚举单例
public enum Singleton_07 {
INSTANCE;
public void test(){
System.out.println("hi~");
}
}
// 使用:
Singleton_07.INSTANCE.test();
举例
impl是各自的实现都继承了ICommodity接口。StoreFactory中通过参数控制调用不同实例。
优点:
缺点:
可能会有非常多的子类 → 应使用其他模式进行优化
抽象工厂是一个中心工厂,可以创建其他工厂的模式。
抽象工厂模式要解决的问题是:在一个产品族,存在多个不同类型的产品(Redis集群、操作系统)的情况下,如何选择接口的问题。
比如原有一个单机Redis,随着业务的发展,有了更健壮的Redis集群A和B(分别提供不同的接口和方法),需要把Redis升级但不能影响目前系统的运行。
将多个简单对象一步步地组装构建出一个复杂对象。
将一个复杂的构建与其表示分离,使得同样的构建过程可以创建不同的表示。(因为每个组装中可以选用不同的原料、元件)
举例:修改前
Matter.java主要保证所有的装修材料可以按照统一标准进行获取。其他类都实现了Matter接口。这样在使用时需要很多个if else。修改后:
IMenu是接口类,DecorationPackageMenu实现了IMenu接口,是填充器,
Builder建造者类具体的各种组装。
DecorationPackageMenu类里有一个List list,一个price,一个area,一个grade(装修等级)
,所以添加matter(组装)的同时可以计算价格和面积啥的,也就可以打印单子了。(以往这些是放在各个类的)。
Builder类只是调用DecorationPackageMenu类中的方法实现组装而已。
何时选择建造者模式?一些基本物料不变,而其组合经常变化时。
原型模式主要解决的问题是创建重复对象,而这种对象内容本身比较复杂,生成过程可能从库或RPC接口中获取数据的耗时较长,因此采用克隆的方式节省时间。
举例:
上机考试抽题服务。有问答题和选择题,未来可能有更多题型。但是题目不能每次都从库或者更远的地方抽取,因为如果创建对象很多的话,会非常耗时。
QuestionBank(实现了Cloneable)负责将各个题目进行组装最终输出试卷,主要包括append()和clone(),clone()里不止复制,更有乱序功能。Controller就是初始化,以及提供createPaper()。
Cloneable是标记型的接口,它们内部都没有方法和属性,实现 Cloneable来表示该对象能被克隆,能使用Object.clone()方法。如果没有实现 Cloneable的类对象调用clone()就会抛出CloneNotSupportedException。
优点:
便于通过克隆方式创建复杂对象,可以避免重复做初始化操作,不需要与类中所属的其他类耦合。
缺点:
如果对象中包括了循环引用的克隆,以及类中深度使用对象的克隆,会使此模式变麻烦。