zt:工厂模式-简单工厂(设计模式的入门级模式—初级)

博客介绍了工厂模式的几种形态,重点阐述简单工厂模式。以Java中书店买书系统为例,对比使用new操作符和工厂模式实例化对象的方式,指出工厂模式能将大量有共同接口的类实例化,且不必事先知道要实例化的类,还能分割实例创建与使用的责任。
 本文综合了《thinking in Design pattern with java》,《Design pattern》,《爪哇语言简单工厂创立性模式介绍》以及我自己的观点,对factory 相关的设计模式进行详细的说明。

工厂模式有以下几种形态:
简单工厂(Simple Factory)模式
工厂方法(Factory Method)模式,又称多形性工厂(Polymorphic Factory)模式
抽象工厂(Abstract Factory)模式,又称工具箱(Kit或Toolkit)模式

以下详细介绍简单工厂模式。

工厂模式是创建型模式,创建型模式抽象了实例化过程。Java中创建对象的方式为使用以下代码:
Book goodBook = new Book();
使用new操作符的短处是事先必须明确知道要实例化的类是什么, 而且实例化的责任往往与使用实例的责任不加区分。上面这句话很难理解,而且大多数人习惯于使用New生命。我们举个例子说明一下工厂的好处:

factory1.png

三个种类的书继承了接口Book,一般情况下声明实例要用到以下代码:
Book chBook = new ChineseBook();
Book enBook = new EnglishBook();
Book jaBook = new JapeneseBook();
这些代码都是大家能理解的,利用多态,我们很好的声明了各种书的实例。建立一个商店买书系统,类图如下:

factory2.png

说明一下:
Shop商店类拥有三种书属性,这些属性将在shop的构造函数中实例化,同时还要实例化用户类,象“书对象”一样,可以生成多个user用户,这并不是我们研究的重点。我们关心如何实例化各个书的实例。
我现实使用了老办法,用New 声明!代码如下:

public class Shop
{
List books = new ArrayList();
String shlist[] = { "ch-a", "ch-b", "en-c", "ja-d",};//书名
public void Shop(){
books.add(new ChineseBook("ch-a"));// ch-a是书的名称
books.add(new ChineseBook("ch-b"));
books.add(new EnglishBook("en-c"));
books.add(new JapeneseBook("ja-d"));//声明了四本书
}
.......
.......
};

四本书被声明完了,得到了四个实例。这样写也用到了很多技巧,似乎无懈可击,可事实上这样写太不合实际了,每当增加一个shlist[]中的元素,都要增加一个new来实例化。仔细观察以下书名”ch-a”与类名”ChineseBook”是很有规律的,完全可以把他们放在一个工厂里加工,产生的成品就是已经实例化完成的书对象了。我们把这个工厂方法放在Shop类中,设成static方法。
把类图稍改一下,可以很明显的看出完美的工厂模型。

factory3.png

具体代码如下:

public class Shop
{
List books = new ArrayList();
String shlist[] = { "ch-a", "ch-b", "en-c", "ja-d",};//书名
public void Shop(){
for(int i = 0; i < shlist.length; i++)
books.add(Shop.bookFactory(shlist[i])); //调用工厂模式
}
public static Book bookFactory(String bookName){ //工厂模式
if(bookName.subString(0,2).equals("ch")) return new ChineseBook(bookName);
if(bookName.subString(0,2).equals("en")) return new EnglishBook(bookName);
if(bookName.subString(0,2).equals("ja")) return new JapeneseBook(bookName);
}
public void sellBook(User someone){
Iterator i = books.iterator(); //跌代模式
while(i.hasNext()) {
Book book = (Book)i.next();
if (book.getName()==someone.needBook()) //以下是具体的逻辑计算,可以不用看
{
book.setUser(someone);
someone.setCash = someone.getCash - book.getPrice();
}
}
.......
cc. Channel.Pattern
.......
}
};

代码中 String shlist[] = { "ch-a", "ch-b", "en-c", "ja-d",};可以随意增加,完全自动化声明。如果增加书的种类,可以直接修改factory方法。工厂模式就是专门负责将大量有共同接口的类实例化,而且不必事先知道每次是要实例化哪一个类的模式。
再回来看看这句话能不能理解“面向对象的设计的目的之一,就是把责任进行划分,以分派给不同的对象。我们推荐这种划分责任的作法, 是因为它和封装(Encapsulation)和分派(Delegation)的精神是相符合的。创立性模式把对象的创立过程封装起来,使得创立实例的责任与使用实例的责任分割开, 并由专门的模块分管实例的创立,而系统在宏观上不再依赖于对象创立过程的细节。”

<think>我们遇到了Elasticsearch启动失败的问题,具体表现为通过systemctl启动时控制进程退出且错误代码为1。根据引用[2]的内容,这种错误通常与文件锁或权限问题有关。下面将逐步分析并解决此问题。 ### 步骤1: 检查服务状态和日志 首先使用以下命令查看详细错误信息: ```bash systemctl status elasticsearch.service ``` 如果输出信息有限,进一步使用journalctl查看完整日志: ```bash journalctl -u elasticsearch.service -xe --no-pager ``` 重点关注以下关键错误: - **文件锁问题**:如引用[2]所述,若出现`Unable to obtain lock on /usr/share/elasticsearch/data/nodes/0`,说明已有ES实例占用数据目录 - **权限问题**:如`Permission denied`类错误,表明ES进程无权访问特定目录 ### 步骤2: 解决文件锁冲突 若日志显示文件锁冲突(常见于重复启动或异常退出后): 1. **检查ES进程是否已运行**: ```bash ps aux | grep elasticsearch ``` 2. **若存在旧进程则强制停止**: ```bash kill -9 <PID> ``` 3. **删除残留锁文件**(谨慎操作): ```bash rm -f /usr/share/elasticsearch/data/nodes/0/node.lock ``` ### 步骤3: 修复目录权限 权限问题通常表现为日志中的`AccessDeniedException`。需确保ES用户(默认为elasticsearch)拥有数据、日志等目录的完整权限: ```bash # 修改数据目录权限 chown -R elasticsearch:elasticsearch /var/lib/elasticsearch # 修改日志目录权限 chown -R elasticsearch:elasticsearch /var/log/elasticsearch # 修改配置文件目录权限 chown -R elasticsearch:elasticsearch /etc/elasticsearch ``` > **注意**:目录路径可能因安装方式不同而异,可通过配置文件`/etc/elasticsearch/elasticsearch.yml`中的`path.data`和`path.logs`确认 ### 步骤4: 检查系统资源限制 ES对系统资源有较高要求,需验证: 1. **最大文件描述符**: ```bash # 临时生效 ulimit -n 65535 # 永久生效(在/etc/security/limits.conf追加) elasticsearch - nofile 65535 ``` 2. **最大虚拟内存**: ```bash # 在/etc/sysctl.conf追加 vm.max_map_count=262144 sysctl -p ``` ### 步骤5: 验证配置文件语法 使用ES自带的配置检查工具: ```bash sudo -u elasticsearch /usr/share/elasticsearch/bin/elasticsearch -d -p pid --enroll-node --verbose ``` 若配置错误,工具会明确提示错误位置。 ### 示例:典型错误处理 **场景**:日志显示`max virtual memory areas vm.max_map_count [65530] is too low` **解决**: ```bash # 临时调整 sysctl -w vm.max_map_count=262144 # 永久生效 echo "vm.max_map_count=262144" >> /etc/sysctl.conf ``` 完成上述步骤后重启服务: ```bash systemctl restart elasticsearch ``` ### 附录:关键目录权限结构 ```tree /etc/elasticsearch/ ├── elasticsearch.yml # 主配置文件 ├── jvm.options # JVM配置 └── ... /var/lib/elasticsearch # 默认数据目录 → 权限: elasticsearch:elasticsearch /var/log/elasticsearch # 默认日志目录 → 权限: elasticsearch:elasticsearch ``` 通过逐步排查锁定问题根源,可针对性解决启动失败问题[^2][^3]。 §§相关问题§§ 1. 如何自定义Elasticsearch的数据存储路径和日志路径? 2. 在Docker容器中运行Elasticsearch时遇到启动失败应如何排查? 3. Elasticsearch启动时提示Java堆大小不合法该如何处理? </think>Elasticsearch 启动失败并返回退出代码 1(通过 systemd 启动失败)是常见问题,通常由文件权限、资源限制或配置错误引起。以下是系统性的排查和解决方案: --- ### 一、核心排查步骤 #### 1. **查看详细错误日志** ```bash # 查看服务状态摘要 systemctl status elasticsearch.service # 查看完整启动日志(关键) journalctl -u elasticsearch.service -xe --no-pager | grep -i error ``` - **重点检查**: - `Permission denied`(权限不足) - `max file descriptors`(文件句柄不足) - `max virtual memory`(内存映射不足) - `Cannot obtain lock`(文件锁冲突) #### 2. **检查数据目录权限**(最常见原因) ```bash # 确认Elasticsearch用户对数据目录的所有权 sudo chown -R elasticsearch:elasticsearch /var/lib/elasticsearch # 验证权限(应显示elasticsearch用户) ls -ld /var/lib/elasticsearch ``` #### 3. **检查文件锁冲突** 若日志出现 `Cannot obtain lock` 错误: ```bash # 删除残留的锁文件 sudo rm -f /var/lib/elasticsearch/nodes/*/node.lock # 重启服务 sudo systemctl restart elasticsearch ``` --- ### 二、系统资源调整 #### 1. **解除文件句柄限制** ```bash # 编辑配置文件 sudo nano /etc/security/limits.conf # 添加以下内容(* 表示对所有用户生效) * soft nofile 65536 * hard nofile 65536 elasticsearch soft memlock unlimited elasticsearch hard memlock unlimited ``` #### 2. **增加虚拟内存映射** ```bash # 临时生效 sudo sysctl -w vm.max_map_count=262144 # 永久生效(写入/etc/sysctl.conf) echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf sudo sysctl -p ``` --- ### 三、配置文件验证 #### 1. **检查关键配置** 编辑 `/etc/elasticsearch/elasticsearch.yml`: ```yaml # 确保以下配置正确 cluster.name: my-cluster node.name: node-1 network.host: 0.0.0.0 # 如需外网访问 discovery.type: single-node # 单节点模式 ``` #### 2. **手动测试启动** ```bash # 切换至elasticsearch用户测试启动 sudo -u elasticsearch /usr/share/elasticsearch/bin/elasticsearch ``` - 观察控制台输出的原始错误信息 --- ### 四、高级故障排除 #### 1. **内存锁定检查** ```bash # 在 /etc/elasticsearch/jvm.options 中调整 -Xms1g # 最小堆内存(根据机器配置调整) -Xmx1g # 最大堆内存(建议不超过物理内存50%) # 禁用内存锁定(如遇内存不足错误) bootstrap.memory_lock: false ``` #### 2. **SELinux 策略调整** ```bash # 临时禁用SELinux(仅用于测试) sudo setenforce 0 # 若问题解决,需永久调整策略 sudo nano /etc/selinux/config SELINUX=permissive ``` --- ### 五、典型解决方案总结 | 错误类型 | 解决方法 | |--------------------------|---------------------------------------------| | **权限不足** | `chown -R elasticsearch:elasticsearch /var/lib/elasticsearch` | | **文件句柄不足** | 修改 `/etc/security/limits.conf` | | **内存映射不足** | `sysctl -w vm.max_map_count=262144` | | **锁文件冲突** | 删除 `/var/lib/elasticsearch/nodes/*/node.lock` | | **堆内存配置错误** | 调整 `/etc/elasticsearch/jvm.options` 中的 `-Xms`/`-Xmx` | > **重要提示**:每次修改配置后需执行 `sudo systemctl daemon-reload` 再重启服务[^1][^3]。 --- ### 六、验证服务状态 ```bash # 检查服务是否运行 curl -X GET "localhost:9200/?pretty" # 预期返回JSON格式的集群信息 { "name" : "node-1", "cluster_name" : "my-cluster", "version" : { ... } } ``` 通过以上步骤逐步排查,95%的退出代码1问题可得到解决。若仍失败,请提供 `journalctl` 的具体错误输出进一步分析[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值