Java设计模式二
今天谈的是工厂模式,该模式用于封装和对对象的创建,万物皆对象,那么万物又是产品类,如一个水果厂生产三种水果罐头,我们就可以将这三种水果作为产品类,再定义一个接口用来设定对水果罐头的生成方法,在工厂类中定义一个方法可以根据我们提供给工厂的不同参数,来生成不同的产品。这样我们就可以方便后续的扩展,例如工厂又新生产另一种水果罐头,那么我们只需要添加相应的水果类,传入工厂相应的制造方法即可。下面我们通过具体的代码来理解工厂模式的实现。
标准的工厂类设计###
工厂类的定义是:定义一个用于创建对象的接口,让子类决定实例化哪个类,工厂方法使得一个类的实例化延迟到子类。我们定义一个水果类(抽象),让苹果,桔子类继承水果类。定义一个工厂(抽象),使用泛型的抽象方法,再定义一个或者多个具体的工厂继承该抽象工厂的抽象方法。生产中当调用工厂时传入想要生产的水果类(具体)即可。
package com.factor;
/**
* 抽象水果类
*/
public abstract class Fruit {
public void getClassname(){
System.out.println("我属于水果");
}
public abstract void getname();
}
package com.factor;
/**
*
* @author Administrator
* 苹果
*/
public class Apple extends Fruit{
public void getname() {
// TODO Auto-generated method stub
System.out.println("我是一个苹果");
}
}
package com.factor;
/**
*
* @author Administrator
* 桔子
*/
public class Orange extends Fruit{
public void getname() {
// TODO Auto-generated method stub
System.out.println("我是一个桔子");
}
}
/**
*
* @author Administrator
* 抽象工厂
*/
public abstract class AbstractFactory {
public abstract <T extends Fruit> T createFriut(Class<T> c);
}
/**
*
* @author Administrator
* 水果工厂
*/
public class FruitFactory extends AbstractFactory {
@Override
public <T extends Fruit> T createFriut(Class<T> c) {
// TODO Auto-generated method stub
System.out.println("开始制作");
Fruit fruit=null;
try {
fruit = (Fruit)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return (T)fruit;
}
}
场景类:
public class Click {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
AbstractFactory factory = new FruitFactory();
Fruit apple = factory.createFriut(Apple.class);
apple.getClassname();
apple.getname();
}
}
运行结果
工厂方法模式拥有良好的封装性,代码结构清晰,另外对对象的创建有约束的作用如上面代码中使用界定限制工厂只能生产水果),其次工厂模式的扩展性也很优秀,如需要增加产品的生产,只添加相应的产品类,适当的修改或者增加一个工厂类即可。我们从工厂方法中也能看到迪米特法则的运用,也就是高层模块只需要知道产品的抽象类,其它的类“不关心”。也可以看出一个产品只依赖产品的抽象这也是符合依赖倒置的。
工厂模式扩展###
1.缩小为简单工厂模式
如果我们只需要一个工厂生产水果,那么我们可以把工厂抽象类中的方法放到具体工厂类中即可。
/**
*
* @author Administrator
* 水果工厂
*/
public class FruitFactory {
public static <T extends Fruit> T createFriut(Class<T> c) {
// TODO Auto-generated method stub
System.out.println("开始制作");
Fruit fruit=null;
try {
fruit = (Fruit)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return (T)fruit;
}
}
这使得我们的类变得简单,而且调用也简单了,所以称为简单工厂模式也叫做静态工厂模式。这样做也存在不符合开闭原则的缺点,不利于扩展。
2.多工厂模式
我们可以使用多个工厂来生产产品,比如有苹果工厂,有桔子工厂等。
/**
*
* @author Administrator
* 多工厂中的抽象工厂 区别: 不适用泛型 直接生成一个产品大类
*/
public abstract class MaxFaxtory {
public abstract Fruit create();
}
具体的工厂类:
/**
*
* @author Administrator
* 多工厂模式
*/
public class AppleFactory extends MaxFaxtory {
@Override
public Fruit create() {
// TODO Auto-generated method stub
return new Apple();
}
/**
*
* @author Administrator
* 所工厂模式 桔子工厂
*/
public class OracleFactory extends MaxFaxtory{
@Override
public Fruit create() {
// TODO Auto-generated method stub
return new Orange();
}
}
这样做使得各个工厂之间职责清晰,结构简单,但也是不利于扩展。我们可以使用一个协调类避免调用者与各个子工厂交流,协调类的作用是封装工厂类,对高层模块提供统一的访问接口。
3.替代单例模式
/**
*
* @author Administrator
* 单例类
*/
public class Singleton {
//不允许new
private Singleton(){
}
public void doSomething(){
}
}
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class SingletonFactory {
private static Singleton singleton;
static{
try {
Class c1=Class.forName(Singleton.class.getName());
Constructor constructor=c1.getDeclaredConstructor();
constructor.setAccessible(true);
singleton = (Singleton)constructor.newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
SingletonFactory通过反射的方法创建一个单例对象。
4.延迟初始化
一个对象被消费完毕后,并不立即释放,而是保持初始状态,等待再次被调用。
/**
*
* @author Administrator
* 延迟加载的工厂类
*/
public class ProductFactory {
private static final Map<String,Fruit> prMap = new HashMap();
public static synchronized Fruit createFruit(String type) throws Exception{
Fruit fruit = null;
if(prMap.containsKey(type)){
fruit = prMap.get(type);
}else{
if(type.equals("apple")){
fruit = new Apple();
}else{
fruit = new Orange();
}
}
return fruit;
}
}
延迟加载的框架易于扩展,可以通过判断Map中已有的对象数量来实现。通过延迟加载也降低了对象生成与销毁带来的问题。
Java设计模式二的更多相关文章
- Java 设计模式(二)-六大原则
Java 设计模式(二)-六大原则 单一职责原则(Single Responsibility Principle) 定义: 不要存在多余一个原因导致类变更,既一个类只负责一项职责. 问题由来: 当类A ...
- java设计模式(二)---工厂方法模式
2普通工厂方法模式 就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建. 2.1创建接口 /** * 发送接口 * Created by mrf on 2016/2/25. */ public ...
- java设计模式(二)
抽象工厂模式 对工厂同一抽象,便于扩展 interface Provider{ public Sender Send(); } class MailFactory implements Provide ...
- Java设计模式(十二) 策略模式
原创文章,同步发自作者个人博客,http://www.jasongj.com/design_pattern/strategy/ 策略模式介绍 策略模式定义 策略模式(Strategy Pattern) ...
- Java设计模式(二) 工厂方法模式
本文介绍了工厂方法模式的概念,优缺点,实现方式,UML类图,并介绍了工厂方法(未)遵循的OOP原则 原创文章.同步自作者个人博客 http://www.jasongj.com/design_patte ...
- Java设计模式(二)抽象工厂模式
一.场景描述 接<Java设计模式(一)工厂模式>https://www.cnblogs.com/mahongbiao/p/8618970.html 工厂模式有一缺点,就是破坏了类的封闭性 ...
- Java 设计模式系列(二十)状态模式
Java 设计模式系列(二十)状态模式 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式.状态模式允许一个对象在其内部状态改变的时候改 ...
- Java 设计模式系列(十二)策略模式(Strategy)
Java 设计模式系列(十二)策略模式(Strategy) 策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以 ...
- Java 设计模式系列(二二)责任链模式
Java 设计模式系列(二二)责任链模式 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求 ...
随机推荐
- binary-heap(二叉堆)原理及C++代码实现
二叉堆可以看做一个近似的完全二叉树,所以一般用数组来组织. 二叉堆可以分为两种形式:最大堆和最小堆.最大堆顾名思义,它的每个结点的值不能超过其父结点的值,因此堆中最大元素存放在根结点中.最小堆的组织方 ...
- ionic3 修改打包时 android sdk 路径
修改 /platforms/android/local.properties 文件
- Winform下编译Dev控件时提示license.licx文件错误
有时候,用vs2005或2008,用到第3方控件的时候会自动生成licenses.licx.我用的是devexpress.在程序运行的时候总是出现dev的画面,很烦.在网上找了找,找到去掉画面的方法: ...
- pandas常用小trick(持续更新)
记录一下pandas常用的小技巧,时间长了干别的去了会忘记,记录一下: 1. 在处理数据过程中涉及到label和null的处理方法 # 方法一 df['height'][df.height < ...
- Date类与SimpleDateFormat类中parse()方法和format()方法
package ppt11util类; import java.text.ParseException; import java.text.SimpleDateFormat; import java. ...
- http接口与webservice接口的区别
常见的API接口有两类:http接口和webservice接口. http接口走http协议,通过路径来区分调用方法,请求报文一般是key-value形式的,返回报文一般是json串,常用的是get和 ...
- LeetCode No.70,71,72
No.70 ClimbStairs 爬楼梯 题目 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数. ...
- python3下scrapy爬虫(第七卷:编辑器内执行scrapy)
之前我们都是在终端切入到scrapy的路境内执行爬虫的,你要多敲多少行的字节,所以这次我们谈谈如何在编辑器里执行,这个你可以用在爬虫中,当你使用PYTHONWEB开发时尽量不要在编辑器内启动端口服务那 ...
- Springboot实现发送邮箱
https://blog.csdn.net/xubin1623875795/article/details/78967141 http://www.cnblogs.com/jmcui/p/975844 ...
- A 小石的签到题
题目链接:https://ac.nowcoder.com/acm/contest/949/A 思路: 这题明确的说了是个签到题,但是一直怀疑不是签到题,是唬我的,结果仔细想了想真是这么回事. 每个人必 ...