目录
设计模式简介与分类
简介
设计模式(英语 design pattern)是对面向对象设计中反复出现的问题的解决方案。这个术语是在1990年代由Erich Gamma等人从建筑设计领域引入到计算机科学中来的。这个术语的含义还存有争议。算法不是设计模式,因为算法致力于解决问题而非设计问题。设计模式通常描述了一组相互紧密作用的类与对象。设计模式提供一种讨论软件设计的公共语言,使得熟练设计者的设计经验可以被初学者和其他设计者掌握。设计模式还为软件重构提供了目标。
随着软件开发社群对设计模式的兴趣日益增长,已经出版了一些相关的专著,定期召开相应的研讨会,而且Ward Cunningham为此发明了WikiWiki用来交流设计模式的经验。
设计模式分为以下三大类:创建型模式、结构模式、行为模式
创建型模式
1、单例模式(Singleton):保证一个类只有一个实例,并提供一个访问它的全局访问点
2、抽象工厂(Abstract Factory):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类。
3、工厂方法(Factory Method):定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到了子类。
4、建造模式(Builder):将一个复杂对象的构建与他的表示相分离,使得同样的构建过程可以创建不同的表示。
5、原型模式(Prototype):用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。
结构模式
6、迭代器模式(Iterator):提供一个方法顺序访问一个聚合对象的各个元素,而又不需要暴露该对象的内部表示。
7、观察者模式(Observer):定义对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知自动更新。
8、模板方法(Template Method):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,TemplateMethod使得子类可以不改变一个算法的结构即可以重定义该算法得某些特定步骤。
9、命令模式(Command):将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队和记录请求日志,以及支持可撤销的操作。
10、状态模式(State):允许对象在其内部状态改变时改变他的行为。对象看起来似乎改变了他的类。
11、策略模式(Strategy):定义一系列的算法,把他们一个个封装起来,并使他们可以互相替换,本模式使得算法可以独立于使用它们的客户。
12、职责链模式(China of Responsibility):使多个对象都有机会处理请求,从而避免请求的送发者和接收者之间的耦合关系
13、中介者模式(Mediator):用一个中介对象封装一些列的对象交互。
14、访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这个元素的新操作。
15、解释器模式(Interpreter):给定一个语言,定义他的文法的一个表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
16、备忘录模式(Memento):在不破坏对象的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
行为模式
17、组合模式(Composite):将对象组合成树形结构以表示部分整体的关系,Composite使得用户对单个对象和组合对象的使用具有一致性。
18、外观模式(Facade):为子系统中的一组接口提供一致的界面,fa?ade提供了一高层接口,这个接口使得子系统更容易使用。
19、代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问
20、适配器模式(Adapter):将一类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作那些类可以一起工作。
21、装饰模式(Decrator):动态地给一个对象增加一些额外的职责,就增加的功能来说,Decorator模式相比生成子类更加灵活。
22、桥模式(Bridge):将抽象部分与它的实现部分相分离,使他们可以独立的变化。
23、享元模式(Flyweight)
创建型模式
原型模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。
优点:
1、创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率
2、不用重新初始化对象,而是动态地获得对象运行时的状态
3、如果原始对象发生变化(增加或者减少属性),其它克隆对象的也会发生相应的变化,无需修改代码
缺点:
1、需要为每一个类配备一个克隆方法,这对全新的类来说不是很难,但对已有的类进行改造时,需要修改其源代码,违背了 ocp 原则
2、实现深克隆的时候可能需要比较复杂的代码
开发中的陷阱
public class Demo1 {
// public static void main(String[] args) {
// HashMap hm1 = new HashMap();
// hm1.put("name","zs");
// hm1.put("sex","女");
// HashMap hm2 = hm1;
// hm1.put("age","18");
// hm2.put("like","男");
// System.out.println(hm1);
// System.out.println(hm2);
// }
// {like=男, sex=女, name=zs, age=18}
// {like=男, sex=女, name=zs, age=18}
// 这里输出的是一模一样的
public static void main(String[] args) {
HashMap hm1 = new HashMap();
hm1.put("name","zs");
hm1.put("sex","女");
HashMap hm2 = (HashMap) hm1.clone();
hm1.put("age","18");
hm2.put("like","男");
System.out.println(hm1);
System.out.println(hm2);
}
// {sex=女, name=zs, age=18}
// {name=zs, like=男, sex=女}
}
案例:
将一只名字为杰克、性别为母的绵羊克隆10份;
要求每只绵羊的属性、性别都一致;
这是没有使用原型模式的
/**
* @author zc
* @site www.javaxl.com
* @company
* @create 2020-02-22 10:45
*/
public class Sheep {
private String name;
private String sex;
public Sheep(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
/**
* @author zc
* @site www.javaxl.com
* @company
* @create 2020-02-22 10:46
*
* 将一只名字为杰克、性别为母的绵羊克隆10份;
* 要求每只绵羊的属性、性别都一致;
*
* 弊端:无法将当前的状态进行复制
*/
public class Client {
public static void main(String[] args) {
Sheep sheep1 = new Sheep("杰西", "母");
Sheep sheep2 = new Sheep("杰西", "母");
Sheep sheep3 = new Sheep("杰西", "母");
Sheep sheep4 = new Sheep("杰西", "母");
Sheep sheep5 = new Sheep("杰西", "母");
Sheep sheep6 = new Sheep("杰西", "母");
Sheep sheep7 = new Sheep("杰西", "母");
Sheep sheep8 = new Sheep("杰西", "母");
Sheep sheep9 = new Sheep("杰西