目录
前言
设计模式(Design pattern)代表了最佳的实践,是软件开发人员在软件开发过程中面临的一般问题的解决方案。通常根据设计模式所解决的问题性质的不同,将其划分为三大类:创建型、结构型、行为型。
具体包括:
创建型:简单工厂模式、工厂方法模式、抽象工厂模式、单例模式、原型模式、建造者模式。
结构型:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
行为型:模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。
其中创建型模式主要给出对象创建时所面临的问题的普适性解决方案,主要特点是将对象的创建过程与调用过程进行分离。
一、简单工厂模式
定义
简单工厂模式就是将对象的创建过程和调用过程分离开,定义一个专门的类来创建其他实体类的对象。一个工厂通常负责创建一部分具有相同或相似特点的实体类,因此通常把这些实体类向上抽象形成抽象类或接口。从而方便在工厂类进行创建实体类对象时进行接收。
角色
- 具体工厂:负责创建自己所负责的某一部分类的实例,通常将创建方法定义为静态,可以在全局状态下不需要创建工厂实例就能创建所需的实例。
- 抽象实体类:一部分具有相同或相似特点的实体类的抽象,抽象类或者接口。
- 具体实体类:需要被创建实例的实体类,继承抽象实体类或实现其接口。
特点
- 优点:直接根据工厂去创建相应的实体类实例,不需要了解该实体类的创建过程及其相关组织,优化了软件体系结构。
- 缺点:高内聚,当实体类增加时,需要去修改工厂类的内部结构,容易在修改过程中出现错误。
实现
/**
* 简单工厂模式
*/
public class FactoryMode {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
Fruit apple = FruitFactory.get("apple");
Fruit banana = FruitFactory.get("banana");
apple.get();
banana.get();
}
}
/**
* 抽象实体接口
*/
interface Fruit{
public void get();
}
/**
* 具体实体类
*/
class Apple implements Fruit{
public void get(){
System.out.println("采集苹果");
}
}
/**
* 具体实体类
*/
class Banana implements Fruit{
public void get(){
System.out.println("采集香蕉");
}
}
/**
* 工厂类
*/
class FruitFactory{
public static Fruit get(String type) throws IllegalAccessException, InstantiationException {
if(type.equalsIgnoreCase("Apple")){
return Apple.class.newInstance();
}else if(type.equalsIgnoreCase("Banana")){
return Banana.class.newInstance();
}else{
return null;
}
}
}
二、工厂方法模式
定义
具体的设计思路和简单工厂类似,主要是解决简单工厂的缺点,即增加新的实体类时,对原有工厂内部的修改。为了避免这种破坏结构的行为,将工厂类也抽象出来,定义一个抽象类或接口。而每一个具体的实体类对应一个专门的工厂类,一个工厂类创建一个实体类的实例。
角色
- 抽象实体类:一类相似类的抽象父类或接口
- 具体实体类:具体需要被工厂创建实例的类
- 抽象工厂类:一类相似工厂类的抽象父类或接口
- 具体工厂类:与实体类一对一相关联,专门创建某一实体类的工厂类
实现
/**
* 工厂方法模式
*/
public class FactoryMethod {
public static void main(String[] args) {
FruitFactory2 appleFactory = new AppleFactory();
Fruit apple = appleFactory.get();
apple.get();
FruitFactory2 bananaFactory = new BananaFactory();
Fruit banana = bananaFactory.get();
banana.get();
}
}
/**
* 抽象实体接口
*/
interface Fruit{
public void get();
}
/**
* 具体实体类A
*/
class Apple implements Fruit{
public void get(){
System.out.println("采集苹果");
}
}
/**
* 具体实体类B
*/
class Banana implements Fruit{
public void get(){
System.out.println("采集香蕉");
}
}
/**
* 抽象工厂接口
*/
interface FruitFactory2{
public Fruit get();
}
/**
* 具体工厂类A
*/
class AppleFactory implements FruitFactory2{
public Fruit get(){
return new Apple();
}
}
/**
* 具体工厂类B
*/
class BananaFactory implements FruitFactory2{
public Fruit get(){
return new Banana();
}
}
三、抽象工厂模式
定义
抽象工厂模式是对上面两种模式的扩充,简单工厂模式我们可以理解为一个点,只有一个工厂,通过判断传进来的实体类的属性生产不同等级的实体类的实例。工厂方法模式可以理解为一条线,多个实体类对应多个工厂,每个工厂对应一个等级的实体类。而抽象工厂模式则将一维变为二维,引入产品族的概念,同一个工厂可以生产同一等级的产品族内的产品实例,不同工厂生产不同不同产品族的所有等级的产品。
简单工厂:
工厂方法:
抽象工厂:
角色
- 抽象实体类:一类相似类的抽象父类或接口
- 具体实体类:具体需要被工厂创建实例的类
- 抽象工厂类:一类相似工厂类的抽象父类或接口
- 具体工厂类:与实体类一对一相关联,专门创建某一实体类的工厂类
实现
/**
* 抽象工厂模式
*/
public class AbstractFactory {
public static void main(String[] args) {
FruitFactory3 northFruitFactory = new NorthFruitFactory();
Fruit northApple = northFruitFactory.getApple();
Fruit northBanana = northFruitFactory.getBanana();
northApple.get();
northBanana.get();
FruitFactory3 southFruitFactory = new SouthFruitFactory();
Fruit southApple = southFruitFactory.getApple();
Fruit southBanana = southFruitFactory.getBanana();
southApple.get();
southBanana.get();
}
}
class NorthApple extends Apple{
public void get(){
System.out.println("采集北方苹果");
}
}
class SouthApple extends Apple{
public void get(){
System.out.println("采集南方苹果");
}
}
class NorthBanana extends Banana{
public void get(){
System.out.println("采集北方香蕉");
}
}
class SouthBanana extends Banana{
public void get(){
System.out.println("采集南方香蕉");
}
}
interface FruitFactory3{
public Fruit getApple();
public Fruit getBanana();
}
class NorthFruitFactory implements FruitFactory3{
public Fruit getApple(){
return new NorthApple();
}
public Fruit getBanana(){
return new NorthBanana();
}
}
class SouthFruitFactory implements FruitFactory3{
public Fruit getApple(){
return new SouthApple();
}
public Fruit getBanana(){
return new SouthBanana();
}
}
四、单例模式
定义
所谓单例,就是在整个系统中某个类只有一个实例,并且需要提供在全局范围内获取该实例的静态方法。
应用
- 在多线程中,多个线程共享一个资源或者操作一个对象
- 在整个程序空间使用全局变量,共享资源
- 在大规模系统中,由于考虑创建对象所耗费的时间,提高性能,只维持一个实例
实现
方式:
- 构造函数私有化
- 提供全局的静态访问方法获取该实例
类别:
- 懒汉式
class Person2{
private static Person2 person;
private Person2(){
}
public static Person2 getPerson(){
if(person == null){
person = new Person2();
}
return person;
}
}
- 饿汉式
class Person1{
private static Person1 person = new Person1();
private Person1(){
}
public static Person1 getPerson(){
return person;
}
}
- 双重检查
//防止在多线程的情况下出现多个单例对象
class Person3{
private static Person3 person;
private Person3(){
}
public static Person3 getPerson(){
if(person == null){//防止未创建对象就获取对象
synchronized (Person3.class){//防止多线程同时进入创建多个对象
if(person == null){//防止上一个对象锁锁住的多个线程进入创建多个对象
person = new Person3();
}
}
}
return person;
}
}
五、原型模式
定义
原型模式以克隆方法为出发点,创建一个与原型实例一模一样的新实例,两个实例的数据结构与数据内容一模一样,但是两个实例的数据互不影响。根据克隆程度分为深度克隆与浅度克隆。浅度克隆指的是只克隆数值,不克隆引用,即新旧两个对象的内部引用所指的还是同一个其他实例对象。而深度克隆则是数值引用均克隆,将旧对象内部引用的其他所有实例对象都克隆一遍,并将其引用交给新的对象。
应用
- 在创建新的对象时,不止希望继承其基类的数据结构,还希望继承其基类的数据内容。
- 希望对目标对象的修改不影响其原型对象的内容
- 需要隐藏克隆对象的细节
实现
- 浅度克隆
class Person4 implements Cloneable{
private int age;
private String name;
private String sex;
private ArrayList<String> friends;
@Override
protected Person4 clone() throws CloneNotSupportedException {
return (Person4)super.clone();
}
}
- 深度克隆
class Person5 implements Cloneable{
private int age;
private String name;
private String sex;
private ArrayList<String> friends;
@Override
protected Person5 clone() throws CloneNotSupportedException {
Person5 person = (Person5)super.clone();
ArrayList<String> newFriends = new ArrayList<String>();
for(String friend : this.friends){
newFriends.add(friend);
}
person.friends = newFriends;
return person;
}
}
六、建造者模式
定义
与工厂模式类似,也是将对象的创建与调用分离开来,不同的是,创建者模式是为创建复合对象而设计的。所谓复合对象,就是该对象内部还有其他对象的引用。因此,将这类对象的创建流程加以抽象,通过子类继承和重载的方式,动态的创建具有复合属性的对象。
角色
- 产品类:被创建的复合型对象
- 建造师抽象类:对建造者进行向上抽象的抽象类或接口
- 建造师实体类:具体的建造者类
- 设计师类:通过指导建造者进行相应的产品的建造生产
实现
public class BuilderType {
public static void main(String[] args) {
//获取建造者
HouseBuilder houseBuilder = new PingFangBuilder();
//获取设计师
HouseDirector director = new HouseDirector();
//设计师指导建造者盖房子
director.buildHouse(houseBuilder);
//从建造者手中取得房子
House house = houseBuilder.getHouse();
//验房
System.out.println(house.getFloor());
System.out.println(house.getHouseTop());
System.out.println(house.getWall());
}
}
/**
* 产品类
*/
class House{
private String floor;
private String wall;
private String houseTop;
public void setFloor(String floor) {
this.floor = floor;
}
public void setWall(String wall) {
this.wall = wall;
}
public void setHouseTop(String houseTop) {
this.houseTop = houseTop;
}
public String getFloor() {
return floor;
}
public String getWall() {
return wall;
}
public String getHouseTop() {
return houseTop;
}
}
/**
* 建造师接口
*/
interface HouseBuilder{
public void setFloor();
public void setWall();
public void setHouseTop();
public House getHouse();
}
/**
* 平房建造师类
*/
class PingFangBuilder implements HouseBuilder{
House house = new House();
@Override
public void setFloor() {
house.setFloor("平房 ---> 地板");
}
@Override
public void setWall() {
house.setWall("平房 ---> 墙");
}
@Override
public void setHouseTop() {
house.setHouseTop("平房 ---> 屋顶");
}
@Override
public House getHouse() {
return house;
}
}
/**
* 设计师类
*/
class HouseDirector{
public void buildHouse(HouseBuilder houseBuilder){
houseBuilder.setFloor();
houseBuilder.setHouseTop();
houseBuilder.setWall();
}
}