zoukankan      html  css  js  c++  java
  • 设计模式之工厂模式Factory

    工厂模式:创建对象的工厂

    为什么要用工厂模式:

    1,解耦
    通过工厂模式可以把对象的创建和使用过程分离。
    2,减少代码量,易于维护
    如果我们直接new一个对象时,如果需要的对象构造方法比较复杂,那么可能需要一连串的代码去创建对象,如果在别的类中又需要创建该对象,那么代码的重复度肯定不小。通过工厂模式的话,我们把对象创建的具体逻辑给隐藏起来了,交给工厂统一管理,这样不仅减少了代码量,以后如果想改代码的话,只需要改一处即可,也方便我们日常的维护。

    假如说,这个工厂现在用来生成蛋糕,下面先来看三个问题(弄懂这三个问题工厂模式翻篇)

    1,任意定制蛋糕口味

    2,任意定制蛋糕口味生产过程

    3,任意定制生产蛋糕产品一族

    一,我们先看第一个问题(任意定制蛋糕口味)

    首先要有蛋糕的父类或者接口

    package com.zl.factory;
    
    public interface Cake {
    
        void eat();
    
    }

    其次是具体的实现类

    package com.zl.factory;
    
    //巧克力口味蛋糕
    public class ChocolateCake implements Cake {
        @Override
        public void eat() {
            System.out.println("eat chocolateCake........");
        }
    }
    package com.zl.factory;
    
    //水果味蛋糕
    public class FruitCake implements Cake {
        @Override
        public void eat() {
            System.out.println("eat fruitCake..........");
        }
    }

    最后就是运用到具体环境中,这里以测试类代替

    package com.zl.factory;
    
    public class Test {
        public static void main(String[] args) {
            //定制水果味蛋糕
            Cake cake = new FruitCake();
            cake.eat();
    
        }
    }

    其实第一个问题就是Java多态

    二,下面来第二个问题(任意定制蛋糕口味生产过程)

    还是一样,先来几个具体的不同口味蛋糕

    package com.zl.factory;
    
    //水果味蛋糕
    public class FruitCake{
    
        public void eat() {
            System.out.println("eat fruitCake..........");
        }
    }
    package com.zl.factory;
    
    //巧克力口味蛋糕
    public class ChocolateCake {
        
        public void eat() {
            System.out.println("eat chocolateCake........");
        }
    }

    来一个蛋糕厂

    package com.zl.factory;
    
    public class SimpleCakeFactory {
    
        public FruitCake createFruitCake(){
            //before processing前置业务,如日志记录
            return new FruitCake();
        }
    
        public ChocolateCake createChocolateCake(){
            //before processing前置业务,如日志记录
            return new ChocolateCake();
        }
    
    }

    最后运用到具体环境中,还是以测试类代替

    package com.zl.factory;
    
    public class Test {
        public static void main(String[] args) {
    
            //生产水果蛋糕
            FruitCake fruitCake = new SimpleCakeFactory().createFruitCake();
            fruitCake.eat();
    
            //生产巧克力蛋糕
            ChocolateCake chocolateCake = new SimpleCakeFactory().createChocolateCake();
            chocolateCake.eat();
    
        }
    }

    这种也就是我们说的简单工厂,不过这种工厂比较混乱,什么蛋糕都生产,不专一

    于是就有了我们说的工厂方法,为每一种口味蛋糕单一生产,废话少说,上代码

    package com.zl.factory;
    
    public class FruitCakeFactory {
    
        public FruitCake create(){
            //before processing前置业务,如日志记录
            return new FruitCake();
        }
    
    }
    package com.zl.factory;
    
    public class ChocolateCakeFactory {
    
        public ChocolateCake create(){
            //before processing前置业务,如日志记录
            return new ChocolateCake();
        }
    }

    三,最后一个问题(任意定制生产蛋糕产品一族)

    我们先来看一下传统的方法,假如我们要生产蛋糕,蛋糕蜡烛,蛋糕包装等蛋糕一族。

    先来三个具体实现类

    package com.zl.abstractFactory;
    
    //水果味蛋糕
    public class FruitCake {
    
        public void eat() {
            System.out.println("eat fruitCake..........");
        }
    }
    package com.zl.abstractFactory;
    
    //红色蜡烛
    public class RedCandle {
    
        public void see(){
            System.out.println("it is red candle");
        }
    
    }
    package com.zl.abstractFactory;
    
    //简约的包装风格
    public class SimpleStyle {
    
        public void style(){
            System.out.println("it is simple...");
        }
    
    }

    具体客户端运用

    package com.zl.abstractFactory;
    
    public class Test {
        public static void main(String[] args) {
    
            FruitCake cake = new FruitCake();
            cake.eat();
            RedCandle candle = new RedCandle();
            candle.see();
            SimpleStyle style = new SimpleStyle();
            style.style();
    
        }
    }

    假如我们要换一个蛋糕套餐,要巧克力口味的,要蓝色的蜡烛和别的类型包装,上面的运用都要改

    下面运用工厂进行改进

    首先,先来抽象的产品,然后让具体的产品去继承即可(产品继承部分,代码省略)

    package com.zl.abstractFactory;
    
    public abstract class Cake {
    
        abstract void eat();
    
    }
    package com.zl.abstractFactory;
    
    public abstract class Candle {
       
        public abstract void see();
    }
    package com.zl.abstractFactory;
    
    public abstract class Style {
    
        public abstract void style();
    
    }

    其次,用抽象的工厂生产抽象的产品

    package com.zl.abstractFactory;
    
    public abstract class AbstractFactory {
    
        abstract Cake createCake();
        abstract Candle createCandle();
        abstract Style createStyle();
    
    }

    最后按照产品族去生产(继承abstractFactory),比如说生产(水果味,红色蜡烛,简约包装风格)这一族蛋糕,我们命名为FirstProductCake

    package com.zl.abstractFactory;
    
    public class FirstProductCake extends  AbstractFactory{
        @Override
        Cake createCake() {
            return new FruitCake();
        }
    
        @Override
        Candle createCandle() {
            return new RedCandle();
        }
    
        @Override
        Style createStyle() {
            return new SimpleStyle();
        }
    }

    具体运用

    package com.zl.abstractFactory;
    
    public class Test {
        public static void main(String[] args) {
    
            AbstractFactory factory = new FirstProductCake();
    
            Cake cake = factory.createCake();
            cake.eat();
            Candle candle = factory.createCandle();
            candle.see();
            Style style = factory.createStyle();
            style.style();
    
    
        }
    }

    当我们要不同的蛋糕套餐时,只需要去定义不同的生产族即可(继承abstractFactory)

    这就是我们说的抽象工厂

    可能到这里有些人有疑问,定义抽象产品直接用接口可以吗?   答案是可以的。这里就要抠语义了,蛋糕,蜡烛这些都是现实生活中存在的的东西,我们只是把它抽象出来,故用抽象类更适合。

    比如说有个东西是“可移动的”,它可以是吃的东西,也可以是交通工具,也可以是动物,此时定义接口更合适。

    (通俗一点,名词适合用抽象类,形容词适合用接口)

    抽象工厂具体运用:比如我们开发了一款游戏,要为不同的英雄设计不同的皮肤,当我们更换英雄皮肤时,英雄外观会发生改变,英雄攻击会有相应的攻击特效,还有回城特效,这就相当于皮肤产品一族。

    最后对比工厂方法和抽象工厂:

    (1)工厂方法适合在产品维度上面去增加修改产品

    (2)抽象工厂适合在产品族维度上面扩展产品套餐

    (3)各有各的优势和不足

    那有没有更完美的工厂,在这两个维度上面都可以扩展,答案,有。

    那就是spring bean工厂,en。。。等读了源码在来分析......

  • 相关阅读:
    SecureCRT使用提示
    毕业论文写作时,那些页眉、页脚中的内容中的横线、回车符难删除问题解决
    ostu进行遥感图像的分割
    有关奇葩的mex编程时的matlab出现栈内存错误的问题
    free 一个指针时【 retval = HeapFree(_crtheap, 0, pBlock);】报错的原因
    matlab坐标轴设置
    Use PRODUCT_USER_PROFILE To Limit User
    mysql只导出表结构或数据
    编程学习要讲究效率和经验
    Unity3D的SerializeField 序列化域名
  • 原文地址:https://www.cnblogs.com/zhulei2/p/13160591.html
Copyright © 2011-2022 走看看