2、简单工厂模式
2.1 基本介绍
1)简单工厂模式是工厂模式家族中,最简单最实用的成员之一。
2)其思想就是定义一个工厂类来控制对象群的实例化,当我们面对需要大量实例一些相同或者不同子类的对象群体时。这样做的好处是使对象创建和功能维护(需要新种类的对象或不在需要某一种类的对象)集中控制在第三方,便于管理,而不用去修改使用方的代码或者提供方的代码,符合开闭原则。
2.2 以一个订单的例子,
披萨有不同的种类,对应不同的订单,对应产生不同的对象,是使用工厂模式很好的例子
/**
* @Description:Pizza的基类,
* @author: snow
* @Date: 2020-03-04
**/
public abstract class Pizza {
private String type;
public abstract void prepare();
public void bake(){
System.out.println("烤" + type + "披萨");
}
public void cut(){
System.out.println("切" + type + "披萨");
}
public void box(){
System.out.println("打包" + type + "披萨");
}
public Pizza(String type){
this.type = type;
}
}
/**
* @Description:两种具体得到Pizza
* @author: snow
* @Date: 2020-03-04
**/
public class CheesePizza extends Pizza {
@Override
public void prepare() {
System.out.println("准备奶酪制作奶酪披萨!!");
}
public CheesePizza(String type){
super(type);
}
}
/**
* @Description:
* @author: snow
* @Date: 2020-03-04
**/
public class ChickenPizza extends Pizza {
@Override
public void prepare() {
System.out.println("准备鸡肉,制作鸡肉披萨");
}
public ChickenPizza(String type){
super(type);
}
}
/**
* @Description:负责生产对象的工厂
* @author: snow
* @Date: 2020-03-04
**/
public class SimplePizzaFactory {
public static Pizza createPizza(String type){
Pizza pizza = null;
if(type.equals("cheese")){
pizza = new CheesePizza("cheese");
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}else if(type.equals("chicken")){
pizza = new ChickenPizza("chicken");
pizza.prepare();
pizza.cut();
pizza.box();
}else{
System.out.println("暂时还没有这个种类的披萨!");
}
return pizza;
}
}
/**
* @Description:订单类
* @author: snow
* @Date: 2020-03-04
**/
public class Order {
private Pizza pizza;
public void doOrder(){
do{
pizza = SimplePizzaFactory.createPizza(getPizzaType());
if(pizza != null){
System.out.println("出售成功!");
}
}while(pizza != null);
}
public String getPizzaType(){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入披萨的种类:");
try {
return reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
public class Test {
public static void main(String[] args) {
Order order = new Order();
order.doOrder();
}
}
3、工厂方法模式
3.1 思路
工厂方法模式是在简单工厂模式的基础上面对新需求的一种该进。即:当我们的工厂要生产的对象,因某些性质而区别其他属性相同的一些对象,所以这些对象可以按照这些为数不多的性质而分为几个大类。创建对象时因这些不同的性质而需要不同的动作可以把它作为一个抽象方法,从而原来简单工厂中的工厂类变成一个抽象类,再根据这些特别的性质去继承抽象工厂类。子类具体实现不同的生产对象的方法。
3.2 举例说明
仍以上面的披萨例子说明,增加新的需求:披萨有上海的披萨和北京的披萨,披萨的种类此时有:上海的鸡肉披萨,上海的奶酪披萨,北京的鸡肉披萨和北京的奶酪披萨。对于显著的地域特征,可以将原来的SimlePizzaFactory如图
4抽象工厂模式
抽象工厂模式是对简单工厂模式和工厂方法的结合
public interface AbsPizzaFactory{
Pizza createPizza(String type);
}
/**
抽象工厂实现类
*/
public class BjPizzaFactyory implements AbsPizzaFactory{
private Pizza pizza;
public Pizza createPizza(String type){
if(type.equlas("cheese")){
pizza = new BjCheesePizza();
pizza.bake();
pizza.cut();
pizza.box();
}else if(type.equals("chicken")){
pizza = new BjChickenPizza();
pizza.bake();
pizza.cut();
pizza.box();
}else{
System.out.println("本店没有这种披萨!")
}
}
}
public class PizzaOrder{
private AbsPizzaFactory factory;
public void setFactory(AbsPizzaFactory pizzaFactory){
this.factory = pizzaFactory;
}
public void deal(){
factory.createPizza();
}
}
将工厂抽象成了抽象工厂和具体实现的子类两层,将原来单个的工厂变成了工厂簇,更利于代码的维护和扩展。
5、原型模式
4.1、 基本介绍
所谓的原型模式是一种用来克隆对象的方法模式。在jdk中提供了最简单的原型模式。
4.2、jdk中最原生的克隆模式
要是有个类的对象具有克隆能力就要重写clone()方法,这是在Object中定义的类。
用jdk中最原始的代码来测试一下
public class Dollar implements Cloneable{
int value;
String description;
public Dollar(int value, String description) {
this.value = value;
this.description = description;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "Dollar{" +
"value=" + value +
", description='" + description + '\'' +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
System.out.println("debug =======>");
return super.clone();
}
}
public interface Cloneable {
}
虽然cloneable体为空,但是但是得实现,不然会抛出CloneNotSupportedException
public static void main(String[] args) {
Dollar dollar = new Dollar(100, "a Hundred dollar");
try {
Object dollar2 = dollar.clone();
System.out.println(dollar2);
System.out.println(dollar2.getClass());
System.out.println(dollar2 == dollar);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
#上面代码执行的结果为
debug =======>
Dollar{value=100, description='a Hundred dollar'}
class com.snow.prototype.simpleprototype.Dollar
false
Process finished with exit code 0
clone方法显然需要改进。
@Override
protected Object clone() {
Dollar dollar=null;
try {
dollar = (Dollar)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return dollar;
}
4.3、 深拷贝和浅拷贝
4.3.1 浅拷贝
1) 对于数据类型是基本数据类型的的成员变量和包装类,浅拷贝会直接进行值传递,就是将该属性值复制一份给新的对象。
2)对于引用数据类型的成员变量(数组、对象)浅拷贝只会进行引用传递。也就是将该成员的引用值(内存地址)复制一份给新的对象。实际上这两个对象的该成员变量指向同一个实例。在这种情况下一个对象对该成员变量进行修改,会影响到其他对象中该成员变量的值。
3)浅拷贝可通过默认的clone方法来实现。
4.3.2、 深拷贝
1)与浅拷贝不同的是深拷贝在拷贝时要为所有的成员变量申请内存空间,复制每个引用数据类型成员变量所引用的对象。
2)通过重写clone方法实现,super.close()之后再对引用数据类型的成员变量进行一一复制。麻烦程度可想而知。
3)通过对象序列化实现(推荐)
/**
* @Description:
* @author: snow
* @Date: 2020-03-05
**/
public class CloneTarget implements Serializable {
private String desc;
private String name;
private Member member;
public CloneTarget(String desc, String name, Member member) {
this.desc = desc;
this.name = name;
this.member = member;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Member getMember() {
return member;
}
public void setMember(Member member) {
this.member = member;
}
@Override
public String toString() {
return "CloneTarget{" +
"desc='" + desc + '\'' +
", name='" + name + '\'' +
", member=" + member +
'}';
}
public CloneTarget deepClone(){
ByteArrayOutputStream bos;
ObjectOutputStream oos;
ByteArrayInputStream bis;
ObjectInputStream ois;
try{
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
Object copy = ois.readObject();
return (CloneTarget) copy;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
public class Member implements Serializable {
private Integer id;
private String name;
public Member(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Member{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
注意作为成员变量的类也要实现Serializable接口。