学习笔记:结构型之装饰模式,创造型模式之工厂模式、抽象工厂模式

本文介绍了Java设计模式中的装饰模式、工厂模式和抽象工厂模式。装饰模式允许动态地给对象添加职责,提供了一种比继承更灵活的方式来扩展功能。工厂模式则定义了一个创建对象的接口,让子类决定实例化哪个类,实现了对象创建的封装。而抽象工厂模式则是为创建一组相关或相互依赖的对象提供一个统一的接口,无需指定它们的具体类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

装饰模式

Decoration Pattern。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。

定义

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。
在这里插入图片描述
装饰模式有以下4个角色:

  • 抽象构建(Component)角色:该角色用于规范需要装饰地对象(原始对象)。
  • 具体构建(Concrete Component)角色:该角色实现抽象构建接口,定义一个需要装饰的原始类。
  • 装饰(Decorator)角色:该角色持有一个构建对象的实例,并定义一个与抽象构建接口一致的接口。
  • 具体装饰(Concrete Decorator)角色:该角色负责对构建啊对象进行装饰。

应用

  1. 优缺点:
    1)装饰类和被装饰类可以独立发展,而不会相互耦合。
    2)装饰模式是继承关系的一个替代方案。装饰类Decorator,不管装饰多少层,返回的对象还是Component。
    3)装饰模式可以动态地扩展一个实现类的功能。
    4)缺点:多层装饰比较复杂。
  2. 使用场景:
    1)需要扩展一个类的功能,或给一个类增加附加功能。
    2)需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
    3)需要为一批类进行改装或加装功能。

实例

通过对裸车进行装饰的过程演示装饰模式的应用。在这里插入图片描述
Car.java

//Component
public interface Car{
	//车的装配
	public void show();
}

Benz.java//ConcreteComponent

//奔驰车(裸车,需要装饰)
public class Benz implements Car{
	public void show(){
		System.out.println("奔驰车的默认颜色是黑色");
	}
}

CarDecorator.java//Decorator

//汽车装饰
public abstract class CarDecorator implements Car{
	private Car car=null;
	public CarDecorator(Car car){
		this.car=car;
	}
	public void show(){
		this.car.show();
	}
}

ConcreteCarDecorator.java

//具体汽车装饰
public class ConcreteCarDecorator extends CarDecorator{
	public ConcreteCarDecorator(Car car){
		super(car);
	}
	//给车进行彩绘
	private void print(){
		System.out.println("在车尾绘制“新手”字样,颜色是紫色");
	}
	//
	private void setGps(){
		System.out.println("安装GPS定位导航系统");
	}
	//
	public void show(){
		super.show();
		this.print();
		this.setGps();
	}
}

ClientDemo.java

public class ClientDemo{
	public static void main(String args[]){
		Car car=new Benz();
		CarDecoration cd=new ConcreteCarDecorator(car);
		cd.show();
	}
}

运行结果如下所示

奔驰车的默认颜色是黑色
在车尾绘制“新手”字样,颜色是紫色
安装GPS定位导航系统

工厂模式

工厂方法模式(Factory Method Pattern)又叫虚拟构造函数(Virtual Constructor)模式或者多态性工厂(Polymorphic Factory)模式。工厂方法模式的用意是定义一个创建产品对象的工厂接口,将实际创建性工作推迟到子类中。
主要解决:主要解决接口选择的问题。

定义

定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
在这里插入图片描述
在工厂方法模式中,共涉及以下4个角色:

  • 抽象工厂(Creator)角色:该角色使工厂方法模式的核心,与应用系统无关,任何在创建对象的工厂类必须实现这个接口。
  • 具体工厂(Concrete Creator)角色:该角色实现了抽象工厂接口,含有与应用密切相关的逻辑,并且受到应用程序的调用以创建产品对象。
  • 抽象产品(Product)角色:该角色负责定义产品的共性,实现对产品最抽象的定义。
  • 具体产品(Concrete Product)角色:该角色实现抽象产品角色所声明的接口,工厂方法模式所创建的每一个对象都是某个具体产品角色的实例。

应用

  1. 优点:
    1)良好的封装性,代码结构清晰。
    2)优秀的可扩展性。
    3)屏蔽产品类。产品类的实现如何变化,调用者都不需要关心,而只需要关心产品的接口,只要产品接口保持不变,系统的上层模块就不需要发生变化。
    4)工厂方法模式是典型的解耦框架
  2. 缺点:
    每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。
  3. 使用场景:
    1)工厂方法模式是new一个对象的替代品,因此在所有需要生成对象的地方都可以使用,但是需要慎重考虑是否需要增加一个工厂类进行管理,增加代码的复杂度。
    2)需要灵活的、可扩展的框架时,可以考虑采用工厂方法模式。
    3)工厂方法模式可以用在异构项目中。
    4)工厂方法模式可以使用在测试驱动开发的框架下。例如,测试一个类A,就需要 将与类A关联的类B也同时产生出来,使用工厂方法模式可以将类B虚拟出来, 避免类A与类B的耦合。

实例

通过农场系统演示工厂方法模式。
在这里插入图片描述
FruitGardener.java

public interface FruitGardener{	
	public Fruit factory();
}

Fruit.java

public interface Fruit{
	public void grow();
	public void harvest();
	public void plant();
}

AppleGardener.java

public class AppleGardener implements FruitGardener{
	public Fruit factory(){
		return new Apple();
	}
}

GrapeGardener.java

public class GrapeGardener implements FruitGardener{
	public Fruit factory(){
		return new Graph();
	}
}

Apple.java

public class Apple implements Fruit{
	private int treeAge;
	public int getTreeAge(){
		return treeAge;
	}
	public void setTreeAge(int treeAge) {
		this.treeAge = treeAge; 
	}
	public void grow() { 
		System.out.println("苹果正在生长..."); 
	}
	public void harvest() { 
		System.out.println("收获苹果"); 
	}
	public void plant() {
		System.out.println("栽种苹果"); 
	} 
}

Grape.java

public class Grape implements Fruit{
	private boolean seedless;
	public bollean isseedless(){
		return seedless;
	}
	public void setSeedless(boolean seedless){
		this.seedless=seedless;
	}
	public void grow() { 
		System.out.println("葡萄正在生长..."); 
	}
	public void harvest() { 
		System.out.println("收获葡萄"); 
	}
	public void plant() { 
		System.out.println("栽种葡萄");
	} 
}

ClientDemo.java

public class ClientDemo{
	public static void main(String[] args){
		//苹果园丁工厂
		FruitGardener fruitgardener=new AppleGardener();
		//通过工厂生产苹果
		Fruit apple=fruitgardener.factory();
		apple.planet();
		apple.grow();
		apple.harvest();
		//葡萄园丁工厂
		fruitgardener=new GrapeGardener();
		//通过工厂生产葡萄。
		Fruit grape=fruitgardener.factory();
		grape.plant();
		grape.grow();
		grape.harvest();
	}
}

抽象工厂模式

Abstract Factory Pattern
主要解决:主要解决接口选择的问题

定义

为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们的具体类。

在有多个业务品种、业务分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式。
在这里插入图片描述
抽象工厂模式中角色与工厂方法类似,也是有4个角色:

  • 抽象工厂(Abstract Factory)角色:该角色是抽象工厂模式的核心,与应用系统无关,任何创建对象的工厂类必须实现这个接口。
  • 具体工厂(Concrete Factory)角色:该角色实现了抽象工厂接口,含有选择合适的产品对象的逻辑,并且受到应用程序的调用以创建产品对象。
  • 抽象产品(Abstract Product)角色:该角色负责定义产品的共性,实现对产品最抽象的定义。
  • 具体产品(Concrete Product)角色:该角色实现抽象产品角色所声明的接口,抽象工厂模式所创建的任何产品对象都是某个具体产品角色的实例。

应用

  1. 优点:
    1)产品族内的约束为非公开状态,在不同的工厂中,各种产品可能具有不同的相互依赖关系,这些依赖关系由工厂封装在其内部,对于工厂的使用者是不可见的。
    2)生产线的扩展非常容易,如果针对同一产品族建立新的生产线,只需实现产品族中的所有产品接口并建立新的工厂即可。
  2. 缺点:产品族本身的扩展非常困难,如果需要在产品族中增加一个新的产品类型,则需要修改多个接口,并且会影响已有的工厂类。
    最大的缺点是:
  3. 使用场景:当一个对象族(或是一组没有任何关系的对象)都有相同的约束,则可以使用抽象工厂模式。

实例

在这里插入图片描述

AbstractWidgetFactory.java//AbstractFactory

public interface AbstractWidgetFactory{
	public Window createWindow();
	public Scrollbar createScrollbar();
}

WidgetFactory1.java//ConcreteFactory1

public class WidgetFactory1{
	public Window createWindow(){
		return new MSwindow();
	}
	public Scrollbar createScrollbar(){
		A
	}
}

WidgetFactory2.java//ConcreteFactory2

public class WidgetFactory2{
	public Window createWindow(){
		return new MotifWindow();
	}
	public Scrollbar createScrollbar{
		B
	}
}

Window.java//AbstractProductA

public interface Window{
	public void setTitle(String s);
	public void repaont();
	public void addScrollbar(...);
}

PMWindow.java//ConcreteProductA1

public class PMWindow implements Window{
	public void setTitle(){...}
	public void repaint(){...}
}

MotifWindow.java//ConcreteProductA2

public class MotifWindow implements Window{
	public void setTitle(){...}
	public void repaint(){...}
}

GUIbuilder.java//辅助类

public class GUIBuilder{
	public void buildWindow(AbstractWidgetFactory widgetFactory){
		Window window=widgetFactory.createWindow();
		Scrollbar scrollbar=widgetFactory.createScrollbar();
		window.setTitle("New Window");
		window.addScrollbar(scrollbar);
	}
}

Client.java

public class Client{
	public static void main(String args[]){
		GUIBuilder builder=new GUIBuilder();
		AbstractWidgeFactory widgetFactory=null;
		if("MOtif")
			widgetFactory=new WidgetFactory2();
		else
			widgetFactory=new WidgetFactory1();
		builder.buildWindow(widgetFactory);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值