文章目录
几种设计模式
- 创建型模式(五种):单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式、。
- 结构型模式(七种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
- 行为型模式(十一种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式
单例模式
简单工厂模式
简单工厂模式
新增一个工厂类:在工厂类通过不同的类型创建不同的产品
优点在于:工厂类包含了必要的逻辑判断,根据客户端传入的条件动态实例化相关的功能类,对于客户端来说,通过工厂生产产品的方式,去除了与具体产品的依赖
缺点在于:当需要增加新得产品时,需要修改工厂类,违背了开放-封闭原则
工厂方法模式:
新增一个抽象工厂类,它定义了创建产品方法的标准。当需要新增产品时,只需要新增新产品的具体工厂类,而不需要修改工厂类。
优化工厂方法
通过反射机制和配置文件,实现不修改客户端代码的基础上,修改具体工厂类。
- 获取配置文件的类名
- 通过反射创建该对象
- 客户端调用上述方法
工厂方法的隐藏(客户端)
在抽象工厂中直接调用抽象产品的业务方法,客户端只需要创建工厂对象就可以调用产品对象的业务方法
工厂方法优缺点
优点:
- 客户端创建产品,只需知道产品对应的工厂,而无需关心具体的产品类以及创建细节
- 系统中加入新产品,无需修改现有代码,只需要添加一个具体工厂类和具体产品即可。完全符合开闭原则
缺点: - 系统添加新产品需要添加具体工厂类 和 具体产品类,增加系统复杂度
- 客户端使用抽象层调用方法,增加系统理解难度
工厂方法使用场景
- 客户端无需知道它所需要创建具体的类以及具体过程
- 想要使得系统更容易扩展
抽象工厂模式
工厂方法模式生产一类产品,而抽象工厂模式生产一个产品族的多类产品。例如生产不同品牌的多类型产品
抽象工厂:声明了一组方法,每一个方法对应一类产品。
具体工厂:每个具体工厂生产一个品牌的产品,每个品牌生产多类产品。
抽象工厂实现
public interface abstractFactory{
public AbstractProductA createProductA(); //创建类型一的商品
public AbstractProductB createProductB(); //创建类型一的商品
}
//创建海尔品牌的多类产品
public class ConcreateFactoryHaior extends abstractFactory{
public AbstractProductA createProductA(){}; //创建类型一的商品
public AbstractProductB createProductB(){}; //创建类型一的商品
}
//创建美的品牌的多类产品
public class ConcreateFactoryMedia extends abstractFactory{
public AbstractProductA createProductA(){}; //创建类型一的商品
public AbstractProductB createProductB(){}; //创建类型一的商品
}
抽象工厂优缺点
优点:
- 增加产品族很方便,无需修改系统
- 客户端限制同一个产品族的对象一起使用
- 客户端创建产品时,只需知道产品对应的工厂,而无需关心具体的产品类以及创建细节
缺点: - 增加产品等级结构很麻烦,需要修改抽象类,违反开闭原则
抽象工厂适用环境
- 客户端无需知道具体的产品和创建过程就可创建对象
- 系统中存在多于一个的产品族
- 系统需要限制同一个产品族的产品在一起使用
- 系统产品等级结构稳定
建造者模式
建造者模式只关乎如何通过各个组件如何一步步的构建复杂对象,将客户端的使用与复杂对象的构建相分离,客户端无需知道复杂对象的装配方式,只需要知道建造者的类型即可。
例如汽车拥有多个组成部件:车轮,方向盘,发动机等,但大多数用户只会直接使用汽车。
建造者模式的数据结构
- 抽象构建者(Builder):
a) 创建复杂对象各个部分的方法:buildPartA(),buildPartB()
b) 返回复杂对象的接口getResult() - 具体构建者(ConcreteBuilder):实现各个部件的具体构造方法,然后返回复杂对象
- 复杂产品(Product):包含多个组成部分
- 指挥者(Director):通过使用Builder的方法,安排复杂对象的构建次序。客户端使用构建者模式构建对象时,只需传入具体的构建者对象,与指挥者交互就可以。
构建者模式实现—电脑的组装
电脑销售相当于指挥者,客户只需要告诉销售电脑类型,电脑销售则调用电脑组装人员组装一台电脑
## 创建产品类
public class product(){
private string parta;
private string partb;
private string partc;
}
## 定义抽象构建者
public abstract class Builder{
protected Product product=new Product();
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
public Product getResult(){
return product;
}
}
## 定义具体构建者,不同的具体构建者,设置具体部件都不一样
public class ConcreteBuilder1 extend Builder{
public abstract void buildPartA(){
product.setPartA("A1");
};
public abstract void buildPartB(){
product.setPartA("A1");
};
public abstract void buildPartC(){
product.setPartA("A1");
};
}
## 定义指挥者1. 隔离客户端与创建过程 2. 控制产品创建过程(builderBuildX是否被调用,多个builderBuildX的先后次序)
public class Director(){
private Builder builder;
public Director(Builder builder){
this.builder=builder;
}
//产品构建与组装方法
public Product construct(){
builder.builderA();
builder.builderB();
builder.builderC();
return builder.getResult();
}
}
指挥者Director:指导具体构建者如何构建产品,它按一定次序调用Builder的buildPartX()方法,并向客户端返回一个完整对象。
指挥者优化
- 省略Director后,合并到Builder
- Builder类加返回boolean值的钩子函数,指挥者通过钩子函数决定是否调用Builder类的方法
建造者的优缺点
优点:
- 客户端无需知道产品细节,通过相同的构建过程构建不同的产品对象
- 客户端使用不同的具体构建者构建不同的产品对象
- 系统精细化控制产品的构建过程,使得构建过程更清晰
缺点: - 构建者创建的产品需要具有较多共同点
- 产品变化不能频繁
构建者模式适合的场景
- 构建的产品对象有复杂的内部结构
- 产品对象组成部分之间有相互依赖,需要指定生成顺序
原型模式(Prototype)
通过复制一个已有对象来获取更多相同或者类似的对象,从而提高相同类型对象的创建效率。
创建对象的工厂就是原型类自身,工厂方法由克隆方法来实现。
原型模式数据结构
- 抽象原型类Prototype:声明克隆方法的接口
- 具体原型类ConcretePrototype:实现克隆方法,返回一个自己克隆的对象
根据复制对象时是否包含对象中的引用类型成员变量,分为浅克隆,深克隆
浅克隆:
若原型对象是值对象,则复制一份给克隆对象
若原型对象是引用对象,则复制一份对象的引用
深克隆:
不管是值对象,还是引用对象,都会复制一份克隆对象
原型对象的实现-创建周报
public abstract class prototype{
public abstract Prototype clone();
}
public class ConcretePrototype extends Prorotype{
private String attr; //成员变量
public Prototype clone(){
Prototype prototype=new ConcretePrototype();
prototype.setAttr(this.attr);
return prototype;
}
}
java语言中的clone方法和Cloneable接口
在java中实现Cloneable接口重写clone方法实现对象的浅克隆
- 实现浅克隆
public abstract class prototype{
public abstract Prototype clone();
}
public class ConcretePrototype extends Prorotype implement Cloneable{
private Attachment attachment;
private String name;
private String date;
private Sting content;
public Prototype clone(){
Object obj=null;
try{
object=super.clone();
}catch(ClassNotSupportException e){
syso("not support");
}
return (Prototype)obj;
}
}
- 实现深克隆
public class ConcretePrototype extends Prorotype implement Serializable{
private Attachment attachment;
private String name;
private String date;
private Sting content;
public Prototype deepClone(){
// 将对象写入流中
ByteArrayOutputStream bao=new ByteArrayOutputStream();
ObjectOutputSream oos=new ObjectOutputSream (bao):
oos.writeObject(this);
// 将对象从流中读出
ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
return (ConcretePrototype )ois.readObject();
}
}
原型管理器
将多个原型对象存储在一个集合中,相当于一个克隆对象的工厂
通过原型管理器对原型对象进行管理,方便对原型对象进行编程。
public class PrototypeManager{
private Map map=new HashMap();
public PrototypeManager{
map.put("a",new ConcretePrototypeA());
map.put("b",new ConcretePrototypeB());
}
public void add(String key,Prototype prototype){
map.put(key,prototype);
}
public Prototype get(Stirng key){
return (Prototype)map.get(key).clone(); //通过克隆方法创建的对象
}
}
原型对象优缺点
优点
- 客户端针对抽象原型类进行编程,扩展性非常好
- 系统提高了创建相同或类似对象的效率
- 系统使用深克隆保存对象的状态,以便需要时使用,可辅助撤销操作
缺点 - 每个类都配备一个克隆方法,修改产品需要修改源代码
- 当对象有嵌套引用时,每一层都要实现深克隆
原型模式适合场景
- 系统创建对象成本高,新对象可通过已有对象复制
- 系统需要保存对象的状态