设计模式

1、单例(Singleton):确保一个类只有一个实例,并提供该实例的全局访问点。

使用一个私有构造函数、一个私有静态变量以及一个公有静态函数来实现。
私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量。
1)懒汉式-线程不安全
     保证线程安全的方式:①加锁(只在创建实例的时候加锁,所以双重判断);
             ②静态内部类,由于static final修饰为常量,存储在方法区,因此可以同时保证延迟创建和线程安全;
             ③枚举实现,可以防止反射攻击;
2)饿汉式-线程安全:直接实例化的方式也丢失了延迟实例化带来的节约资源的好处

2、简单工厂(Simple Factory):在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口

//简单工厂把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪个具体子类来实例化。
public class SimpleFactory {

    public Product createProduct(int type) {
        if (type == 1) {
            return new ConcreteProduct1();
        } else if (type == 2) {
            return new ConcreteProduct2();
        }
        return new ConcreteProduct();
    }
}


public class Client {

    public static void main(String[] args) {
        SimpleFactory simpleFactory = new SimpleFactory();
        Product product = simpleFactory.createProduct(1);
        // do something with the product
    }
}

3、工厂方法(Factory Mrthod):定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。

//在简单工厂中,创建对象的是另一个类,而在工厂方法中,是由子类来创建对象。
//Factory 有一个 doSomething() 方法,这个方法需要用到一个产品对象,这个产品对象由 factoryMethod() 方法创建。该方法是抽象的,需要由子类去实现
public abstract class Factory {
    abstract public Product factoryMethod();
    public void doSomething() {
        Product product = factoryMethod();
        // do something with the product
    }
}

public class ConcreteFactory extends Factory {
    public Product factoryMethod() {
        return new ConcreteProduct();
    }
}

public class ConcreteFactory1 extends Factory {
    public Product factoryMethod() {
        return new ConcreteProduct1();
    }
}

public class ConcreteFactory2 extends Factory {
    public Product factoryMethod() {
        return new ConcreteProduct2();
    }
}

4、抽象工厂(Abstract Factory):提供一个接口,用于创建 相关的对象家族

抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。
抽象工厂模式用到了工厂方法模式来创建单一对象,AbstractFactory 中的 createProductA() 和 createProductB() 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂方法模式的定义。
至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要同时创建出这两个对象。

public class AbstractProductA {
}
public class AbstractProductB {
}
public class ProductA1 extends AbstractProductA {
}
public class ProductA2 extends AbstractProductA {
}
public class ProductB1 extends AbstractProductB {
}
public class ProductB2 extends AbstractProductB {
}
public abstract class AbstractFactory {
    abstract AbstractProductA createProductA();
    abstract AbstractProductB createProductB();
}
public class ConcreteFactory1 extends AbstractFactory {
    AbstractProductA createProductA() {
        return new ProductA1();
    }

    AbstractProductB createProductB() {
        return new ProductB1();
    }
}
public class ConcreteFactory2 extends AbstractFactory {
    AbstractProductA createProductA() {
        return new ProductA2();
    }

    AbstractProductB createProductB() {
        return new ProductB2();
    }
}
public class Client {
    public static void main(String[] args) {
        AbstractFactory abstractFactory = new ConcreteFactory1();
        AbstractProductA productA = abstractFactory.createProductA();
        AbstractProductB productB = abstractFactory.createProductB();
        // do something with productA and productB
    }
}

5、生成器(Builder):封装一个对象的构造过程,并允许按步骤构造。

Builder模式主要用于“分步骤构建一个复杂对象”。在这其中“分步骤”是一个稳定算法,而复杂对象的各个部分则经常变化。

6、原型模式(Prototype):使用原型实例指定要创建对象的类型,通过复制这个原型来创建新对象。

Prototype模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用Prototype模式创建的实例,具有与原型一样的数据。

1)由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身。

2)目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型对象具有相同的结构,还与原型对象具有相同的值。

3)根据对象克隆深度层次的不同,有浅度克隆与深度克隆。

适用情况: 一个复杂对象,具有自我复制功能,统一一套接口。 对于对象比较复杂,每创建一次new 都会浪费好多的资源和时间 且在初始化的信息不发生变化的前提下 克隆是最好的办法,
public abstract class Prototype {
    abstract Prototype myClone();
}

public class ConcretePrototype extends Prototype {

    private String filed;

    public ConcretePrototype(String filed) {
        this.filed = filed;
    }

    @Override
    Prototype myClone() {
        return new ConcretePrototype(filed);
    }

    @Override
    public String toString() {
        return filed;
    }
}

public class Client {
    public static void main(String[] args) {
        Prototype prototype = new ConcretePrototype("abc");
        Prototype clone = prototype.myClone();
        System.out.println(clone.toString());
    }
}

 7、责任链(Chain Of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。

8、命令(Command):将命令封装成对象中,具有以下作用:

  • 使用命令来参数化其它对象
  • 将命令放入队列中进行排队
  • 将命令的操作记录到日志中
  • 支持可撤销的操作
Command:命令
Receiver:命令接收者,也就是命令真正的执行者
Invoker:通过它来调用命令
Client:可以设置命令与命令的接收者

9、解释器(Interpreter):为语言创建解释器,通常由语言的语法和语法分析来定义.

10、迭代器(Iterator):提供一种顺序访问聚合对象元素的方法,并且不暴露聚合对象的内部表示。

  Iterator 主要定义了 hasNext() 和 next() 方法。

11、中介者(Mediator):集中相关对象之间复杂的沟通和控制方式。

12、备忘录(Memento):在不违反封装的情况下获得对象的内部状态,从而在需要时可以将对象恢复到最初状态。

13、观察者(Observer):定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。

14、状态(State):允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它所属的类。

15、策略(Strategy):定义一系列算法,封装每个算法,并使它们可以互换。策略模式可以让算法独立于使用它的客户端。

状态模式的类图和策略模式类似,并且都是能够动态改变对象的行为。但是状态模式是通过状态转移来改变 Context 所组合的 State 对象,而策略模式是通过 Context 本身的决策来改变组合的 Strategy 对象。
所谓的状态转移,是指 Context 在运行过程中由于一些条件发生改变而使得 State 对象发生改变,注意必须要是在运行过程中。 状态模式主要是用来解决状态转移的问题,当状态发生转移了,那么 Context 对象就会改变它的行为;而策略模式主要是用来封装一组可以互相替代的算法族,并且可以根据需要动态地去替换 Context 使用的算法。

16、模板方法(Template Method):定义算法框架,并将一些步骤的实现延迟到子类。通过模板方法,子类可以重新定义算法的某些步骤,而不用改变算法的结构。

17、访问者(Vister):为一个对象结构(比如组合结构)增加新能力。

18、空对象(Null):使用什么都不做的空对象来代替 NULL。一个方法返回 NULL,意味着方法的调用端需要去检查返回值是否是 NULL,这么做会导致非常多的冗余的检查代码。并且如果某一个调用端忘记了做这个检查返回值,而直接使用返回的对象,那么就有可能抛出空指针异常。

19、适配器(Adaptor):把一个类接口转换成另一个用户需要的接口。

20、桥接(Bridge):将抽象与实现分离开来,使它们可以独立变化。

Abstraction:定义抽象类的接口
Implementor:定义实现类接口

21、组合(Composite):将对象组合成树形结构来表示“整体/部分”层次关系,允许用户以相同的方式处理单独对象和组合对象。

组件(Component)类是组合类(Composite)和叶子类(Leaf)的父类,可以把组合类看成是树的中间节点。
组合对象拥有一个或者多个组件对象,因此组合对象的操作可以委托给组件对象去处理,而组件对象可以是另一个组合对象或者叶子对象。

22、装饰(Decorator):为对象动态添加功能。

装饰者(Decorator)和具体组件(ConcreteComponent)都继承自组件(Component),具体组件的方法实现不需要依赖于其它对象,而装饰者组合了一个组件,这样它可以装饰其它装饰者或者具体组件。所谓装饰,就是把这个装饰者套在被装饰者之上,从而动态扩展被装饰者的功能。装饰者的方法有一部分是自己的,这属于它的功能,然后调用被装饰者的方法实现,从而也保留了被装饰者的功能。可以看到,具体组件应当是装饰层次的最低层,因为只有具体组件的方法实现不需要依赖于其它对象。

类应该对扩展开放,对修改关闭:也就是添加新功能时不需要修改代码。

23、外观(Facade):提供了一个统一的接口,用来访问子系统中的一群接口,从而让子系统更容易使用。

 

posted @ 2020-06-10 15:30  kkzhang  阅读(221)  评论(0编辑  收藏  举报