设计模式-工厂方法模式

工厂方法模式

  • 简单工厂模式:
    • 工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。
    • 但是在我们添加功能的时候,就要修改原有的工厂类去添加分支判断条件,即不但扩展开放,修改也开放了,违背了软件设计中的开放-封闭原则。
    • 工厂方法出现。

工厂方法模式

  • 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。
  • Product接口:定义工厂方法所创建的对象的接口
  • ConcreteProduct:具体的产品,实现了Product接口
  • Creator:声明工厂方法,该方法返回一个Product类型的对象
  • ConcreteCreator:重定义工厂方法以返回一个ConcreteProduct实例
  • 工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在,即工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。
书中的例子
	class LeiFeng{
		public void Sweep(){...};
		public void Wash(){...};
		public void Buf(){...};
	}
	class Undergraduate extends LeiFeng(){}
	class Volunteer extends LeiFeng(){}S
	//以往的简单工厂类实现
	class SimpleFactory{
		public static LeiFeng CreateLeiFeng(String type){
			LeiFeng result = null;
			switch(type){
				case "...":
					result = new Undergraduate();
					break;
				case "...":
					result = new Volunteer();
					break;
			}
			return result;
		}
	}
	//客户端代码
	LeiFeng StudentA = SimpleFactory.CreateFactory("...");
	StudentA.Sweep();
	LeiFeng StudentB = SimpleFactory.CreateFactory("...");
	StudentB.Wash();
	LeiFeng StudentC = SimpleFactory.CreateFactory("...");
	StudentC.Buy();
  • 使用简单工厂模式时,需要在任何实例化的时候都要写出该工厂
	//工厂方法模式实现
	interface IFactory{ LeiFeng CreateLeiFeng();}
	class UndergraduateFactory implements IFactory{
		public LeiFeng createLeiFeng(){
			return new Undergradute();
		}
	}
	class VolunteerFactory implements IFactory(){
		public LeiFeng createLeiFeng(){
			return new Volunteer();
		}
	}
	//客户端代码
	IFactory factory = new UndergraduateFactory();
	LeiFeng student = factory.CreateLeiFeng();
	student.Sweep();
	student.Wash();
	student.Buy();
  • 工厂方法克服了简单工厂违背开放-封闭的缺点,又保持了封装对象创建过程的优点
<think>好的,我现在需要帮助用户实现流星雨动画效果,使用HTML、CSS和JavaScript。首先,我得回忆一下相关知识。用户提到了站内引用里的例子,用Canvas和JavaScript实现,所以应该基于这个技术。 首先,确定使用HTML5 Canvas,因为Canvas适合处理动态图形和动画。然后,考虑如何创建流星对象,每个流星应该有位置、速度、长度等属性。需要用到面向对象编程,每个流星是一个实例,包含更新和绘制的方法。 接下来,动画循环是关键,使用requestAnimationFrame来实现流畅的动画效果。流星的运动轨迹可能需要随机生成角度,让它们从不同方向飞过。此外,流星的拖尾效果可以用渐变的线段模拟,透明度逐渐降低,这样看起来更自然。 还要考虑性能优化,比如当流星移出画布后,重新初始化它们的位置,避免创建过多对象导致内存问题。颜色数组可以增加流星的多样性,随机选择颜色让效果更生动。 用户可能需要代码结构清晰,所以分步骤讲解:设置Canvas、创建流星类、生成流星实例、动画循环、绘制和更新逻辑。同时,补充说明如何调整参数,比如流星数量、速度、长度,方便用户自定义。 最后,根据引用内容,用户可能对交互功能或进一步优化感兴趣,所以在相关问题里提到添加交互或性能调整,帮助用户扩展功能。确保代码注释清楚,解释各部分的作用,让用户容易理解和修改。</think>### 如何实现HTML流星雨动画效果 以下是使用HTML5 Canvas和JavaScript实现流星雨动画的完整方案,包含关键代码和实现逻辑: #### 一、基础结构搭建 1. 创建HTML骨架 ```html <!DOCTYPE html> <html> <head> <style> canvas { background: #000; display: block; } body { margin: 0; overflow: hidden; } </style> </head> <body> <canvas id="meteorCanvas"></canvas> <script src="meteor.js"></script> </body> </html> ``` #### 二、JavaScript核心实现 ```javascript // meteor.js const canvas = document.getElementById('meteorCanvas'); const ctx = canvas.getContext('2d'); // 设置画布全屏 function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } window.addEventListener('resize', resizeCanvas); resizeCanvas(); // 流星类 class Meteor { constructor() { this.reset(); this.colors = ['#ffffff', '#66ccff', '#ff99ff', '#ff6666']; // 多种颜色选择 } reset() { this.x = Math.random() * canvas.width; this.y = -50; this.length = 10 + Math.random() * 30; // 随机长度 this.speed = 3 + Math.random() * 5; // 随机速度 this.angle = 45 + (Math.random() - 0.5) * 30; // 随机角度 this.color = this.colors[Math.floor(Math.random()*this.colors.length)]; } update() { this.x += this.speed * Math.cos(this.angle * Math.PI / 180); this.y += this.speed * Math.sin(this.angle * Math.PI / 180); if (this.y > canvas.height + 100) { this.reset(); } } draw() { ctx.strokeStyle = this.color; ctx.beginPath(); ctx.lineWidth = 2; ctx.moveTo(this.x, this.y); // 创建拖尾效果 for(let i = 0; i < this.length; i++) { const alpha = 1 - i/this.length; ctx.globalAlpha = alpha; ctx.lineTo( this.x - i * Math.cos(this.angle * Math.PI / 180), this.y - i * Math.sin(this.angle * Math.PI / 180) ); } ctx.stroke(); ctx.globalAlpha = 1; // 重置透明度 } } // 创建流星数组 const meteors = Array(30).fill().map(() => new Meteor()); // 动画循环 function animate() { ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; ctx.fillRect(0, 0, canvas.width, canvas.height); meteors.forEach(meteor => { meteor.update(); meteor.draw(); }); requestAnimationFrame(animate); } animate(); ``` #### 三、效果增强技巧 1. 拖尾优化:通过线性渐变增加真实感 ```javascript // 在draw方法中替换strokeStyle设置 const gradient = ctx.createLinearGradient( this.x, this.y, this.x - this.length * Math.cos(this.angle * Math.PI / 180), this.y - this.length * Math.sin(this.angle * Math.PI / 180) ); gradient.addColorStop(0, this.color + 'ff'); gradient.addColorStop(1, this.color + '00'); ctx.strokeStyle = gradient; ``` 2. 添加星空背景(在animate函数开头添加): ```javascript // 绘制星空 if(Math.random() < 0.05) { // 控制星星密度 ctx.fillStyle = `rgba(255,255,255,${Math.random()})`; ctx.fillRect( Math.random() * canvas.width, Math.random() * canvas.height, 1.5, 1.5 ); } ``` #### 四、参数调整建议 1. 流星数量:修改`Array(30)`中的数值 2. 速度范围:调整`this.speed`的随机范围 3. 颜色方案:修改`this.colors`数组 4. 运动角度:调整`this.angle`的计算公式 该实现方案通过Canvas的绘图能力和面向对象编程,实现了流畅的流星雨效果。通过控制流星实例的属性和绘制方式,可以达到较好的性能表现[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值