둘째, 디자인 패턴 및 공장 패턴 개요 상세

둘째, 내부 장기 심장 디자인 패턴의 건축가

내부 장기 심장 디자인 패턴 2. 건축가

2.1. 과정 목표

(1)이 장에 대한 연구를 통해 디자인 패턴의 기원을 이해하는 것입니다.

2, 출시는 디자인 패턴은 우리가 어떤 문제를 해결하는 데 도움이 될 수 있습니다.

3, 기원과 응용 시나리오 공장 모드의 역사 분석.

2.2. 컨텐츠 타겟팅

디자인 패턴 없이는 불가능 아니라, 좋은 디자인 패턴은 우리가 더 실질적인 문제를 해결하는 데 도움이 될 수 있습니다와 함께, 가장 중요한 디자인 패턴이
분리된다. 매일 사용 패턴을 디자인하지만, 자신의하지만 인식. 우리는 주제로 디자인 패턴을 중심으로 연구 패턴을 설계
교훈을 배운 방법, 자신의 사용에 대한 경험을. 사업이 달성하기 위해 매우 효과적인 기술을 필요로 번역하는 디자인 패턴을 배우고 또한 운동
방법을.

2.3. 소프트웨어 설계의 원칙을 불러 오기

디자인 원칙 설명
개방 - 폐쇄 원칙 수정 폐쇄, 확장 오픈
의존 관계 역전 원칙 각각의 클래스를 추상화 또는 모듈에 의해 서로 느슨한 결합에 영향을 미치지 않습니다.
단일 책임 원칙 클래스, 인터페이스, 메소드, 단 한 가지.
인터페이스 독방 원리 인터페이스의 순도를 보장하기 위해 시도, 클라이언트가 원하지 않는 인터페이스를하지 의존한다.
데메테르 또한 적어도 알고, 노하우의 원칙으로 알려져, 더 클래스는 클래스에 따라 달라집니다.
리히터 대체 원칙 서브 클래스는 상위 클래스의 기능을 확장 할 수 있지만, 원래의 함수의 부모 클래스를 변경할 수 없습니다.
다중화하는 원리의 합성 코드 재사용에 반대 상속 관계를 이용하지 않고, 물체의 조성물, 중합을 활용한다.

2.4. 디자인 패턴 개요

쓰기 우아한 코드

더 나은 재건 프로젝트

클래식 프레임 워크는 디자인 패턴의 문제를 해결하기 위해입니다

봄을 볼 수있을 것이다 클래스의 이름에서, 사실 고전적인 프레임 워크의 머리와 디자인 패턴, 그리고 내가 그들을 나열합니다 :

디자인 패턴의 이름 예를 들면
공장 패턴 BeanFactory에
장식 BeanWrapper를
프록시 모드 AopProxy
위임 모드 DispatcherServlet에
전략 모드 처리기 매핑
어댑터 모드 핸들러 어댑터
템플릿 모드 JdbcTemplate을
옵저버 패턴 ContextLoaderListener에

우리의 과정은 IOC, AOP, MVC, JDBC의 주위에 봄 것입니다
확장의 아이디어 있도록 설계 유형에 따라 순서를 설명하기 위해 설계되었습니다 :

유형 이름 영문
스키마 만들기 공장 패턴 공장 패턴
싱글 싱글 톤 패턴
프로토 타입 모드 프로토 타입 패턴
구조 모델 어댑터 모드 어댑터 패턴
장식 장식 후두둑
프록시 모드 프록시 패턴
행동 패턴 전략 모드 전략 패턴
템플릿 모드 템플릿 패턴
위임 모드 위임 패턴
옵저버 패턴 옵저버 패턴

3. 자세한 공장 패턴

역사적 기원 3.1. 공장 패턴

원시 사회 자급 자족 (NO 공장), 작은 농업 공동체 워크숍 ( 간단한 공장 , 민속 와인
광장), 산업 혁명 라인 ( 공장 방법 , 자체 개발), 현대 산업 체인 파운드리 ( 추상적 인 공장 , 폭스콘)

3.2. 간단한 공장 패턴

3.2.1 정의

간단한 공장 패턴 (단순 공장 패턴) 클래스 제품의 인스턴스를 생성하는 팩토리 객체에 의해 결정 의미,
하지만 GOF (23) 디자인 패턴에 속하지 않습니다. 장면을 만들기위한 책임이 작은 물체에 적합한 간단한 공장 수준의 시설 및 클라이언트 필요는
상관 없어 논리의 객체를 생성하는 방법 팩토리 클래스에 매개 변수를 전달합니다.

3.2.2.demo

public class SimpleFactoryTest {
    public static void main(String[] args) {
        CourseFactory factory = new CourseFactory();
        ICourse course = factory.create(JavaCourse.class);
        course.record();
    }
}

public class JavaCourse implements ICourse {
    public void record() {
        System.out.println("录制Java课程");
    }
}

public class CourseFactory {
    public ICourse create(Class<? extends ICourse> clazz){
        // 反射
        try {
            if (null != clazz) {
                return clazz.newInstance();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

3.2.3. 소스

  • Calendar.getInstance ()

  • LoggerFactory.getLogger ()

JDK 소스의 간단한 공장 패턴이 우리가 이제 일정 클래스로, 예를 하나 들어, 어디에서나 볼
Calendar.getInstance () 메소드를 다음 캘린더의 클래스를 만들 수있는 개방형 콘크리트는 다음과 같습니다

    private static Calendar createCalendar(TimeZone zone,
                                           Locale aLocale)
    {
        CalendarProvider provider =
            LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                 .getCalendarProvider();
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException iae) {
                // fall back to the default instantiation
            }
        }

        Calendar cal = null;

        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                switch (caltype) {
                case "buddhist":
                cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case "japanese":
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case "gregory":
                    cal = new GregorianCalendar(zone, aLocale);
                    break;
                }
            }
        }
        if (cal == null) {
            // If no known calendar type is explicitly specified,
            // perform the traditional way to create a Calendar:
            // create a BuddhistCalendar for th_TH locale,
            // a JapaneseImperialCalendar for ja_JP_JP locale, or
            // a GregorianCalendar for any other locales.
            // NOTE: The language, country and variant strings are interned.
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                       && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
        return cal;
    }

우리는 종종 logback을가 사용, 우리는 LoggerFactory 메소드 오버로드보다 더 있다는 것을 알 수
getLogger () :

    public static Logger getLogger(String name) {
        ILoggerFactory iLoggerFactory = getILoggerFactory();
        return iLoggerFactory.getLogger(name);
    }

    public static Logger getLogger(Class clazz) {
        return getLogger(clazz.getName());
    }

3.2.4 장점과 단점

  • 이점
    • 단순한
  • 缺点
    • 工厂类的职责相对过重,不易于扩展过于复杂的产品结构。

3.3.工厂方法模式

3.3.1.定义

工厂方法模式(Factory Method Pattern)是指定义一个创建对象的接口,但让实现这个接口的类
来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。在工厂方法模式中用户只需要关心所
需产品对应的工厂,无须关心创建细节,而且加入新的产品符合开闭原则。

3.3.2.demo

public class FactoryMethodTest {
    public static void main(String[] args) {
        // Python课程工厂
        ICourseFactory factory = new PythonCourseFactory();
        ICourse course = factory.create();
        course.record();

        // Java课程工厂
        factory = new JavaCourseFactory();
        course = factory.create();
        course.record();
    }
}

public class JavaCourseFactory implements ICourseFactory {
    public ICourse create() {
        return new JavaCourse();
    }
}

public interface ICourseFactory {
    ICourse create();
}

public class JavaCourse implements ICourse {
    public void record() {
        System.out.println("录制Java课程");
    }
}

public interface ICourse {
    void record();
}

3.3.3.源码

ApplicationContext就是工厂方法模式

再来看看logback中工厂方法模式的应用,看看类图就OK了:

3.3.4.优缺点

  • 工厂方法适用于以下场景:
    1. 创建对象需要大量重复的代码。
    2. 客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。
    3. 一个类通过其子类来指定创建哪个对象。
  • 工厂方法也有缺点:
    1. 类的个数容易过多,增加复杂度。
    2. 增加了系统的抽象性和理解难度。

3.4.抽象工厂模式

3.4.1.定义

抽象工厂模式(AbastractFactory Pattern)是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。客户端(应用层)不依赖于产品类实例如何被创建、实现等细节,强调的是一
系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。需要提供一个产品类
的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

讲解抽象工厂之前,我们要了解两个概念产品等级结构产品族,看下面的图:

image-20200225191403439

从上图中看出有正方形,圆形和菱形三种图形,相同颜色深浅的就代表同一个产品族,相同形状的代表
同一个产品等级结构。同样可以从生活中来举例,比如,美的电器生产多种家用电器。那么上图中,颜
色最深的正方形就代表美的洗衣机、颜色最深的圆形代表美的空调、颜色最深的菱形代表美的热水器,
颜色最深的一排都属于美的品牌,都是美的电器这个产品族。再看最右侧的菱形,颜色最深的我们指定
了代表美的热水器,那么第二排颜色稍微浅一点的菱形,代表海信的热水器。同理,同一产品结构下还
有格力热水器,格力空调,格力洗衣机。

再看下面的这张图,最左侧的小房子我们就认为具体的工厂,有美的工厂,有海信工厂,有格力工厂
每个品牌的工厂都生产洗衣机热水器空调

image-20200225191741688

3.4.2.demo

public class AbstractFactoryTest {
    public static void main(String[] args) {
        JavaCourseFactory factory = new JavaCourseFactory();
        factory.createNote().edit();
        factory.createVideo().record();
    }
}

/**
 * 抽象工厂CourseFactory类:
 * 抽象工厂是用户的主入口
 * 在Spring中应用得最为广泛的一种设计模式
 * 易于扩展
 */
public abstract class CourseFactory {
    public void init(){
        System.out.println("初始化基础数据");
    }
    protected abstract INote createNote();
    protected abstract IVideo createVideo();
}

/**
 * 创建Java产品族的具体工厂JavaCourseFactory
 */
public class JavaCourseFactory extends CourseFactory {
    public INote createNote() {
        super.init();
        return new JavaNote();
    }
    public IVideo createVideo() {
        super.init();
        return new JavaVideo();
    }
}

/**
 * 创建Java产品族,Java视频JavaVideo类:Java视频
 */
public class JavaVideo implements IVideo {
    public void record() {
        System.out.println("录制Java视频");
    }
}

/**
 * 录播视频:IVideo接口
 */
public interface IVideo {
    void record();
}

/**
 * 扩展产品等级Java课堂笔记JavaNote类:Java笔记
 */
public class JavaNote implements INote {
    public void edit() {
        System.out.println("编写Java笔记");
    }
}

/**
 * 课堂笔记:INote接口
 */
public interface INote {
    void edit();
}

// 创建Python产品族的具体工厂PythonCourseFactory省略。。。

上面的代码完整地描述了两个产品族Java课程和Python课程,也描述了两个产品等级视频和手记。抽象工厂非常完美清晰地描述这样一层复杂的关系。但是,不知道大家有没有发现,如果我们再继续扩展
产品等级,将源码 Source也加入到课程中,那么我们的代码从抽象工厂,到具体工厂要全部调整,很显然不符合开闭原则。

3.4.3.源码

AbstractFactory

AnnotationApplicationContext

Xml

适合长时间不变动的场景

3.4.3.优缺点

抽象工厂缺点

  1. 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口。
  2. 增加了系统的抽象性和理解难度。

3.5.简单工厂 vs 工厂方法 vs 抽象工厂

简单工厂:产品的工厂

工厂方法:工厂的工厂

抽象工厂:复杂产品的工厂

简单工厂:工厂是一个实体类,内部直接根据逻辑创建对应的产品。

工厂方法:工厂首先有个接口定义规范。不同的产品使用不同的实体类工厂根据规范和需求创建对应的产品。这就是它们的区别。

工厂方法是生产一类产品,抽象工厂是生产一个产品族

3.6.作业

1、工厂类一定需要将构造方法私有化吗,为什么?

不一定。抽象工厂类就不能,否则父类的私有构造方法就不能被子类调用。

2、用工厂模式设计支付业务场景,包含跨境支付,支付宝、微信、银联支付,并画出类图。

/**
 * description: 支付接口
 */
public interface IPay {
    /**
     * 支付方法
     */
    void pay();
}

/**
 * description: 支付宝支付
 */
public class AliPay implements IPay {
    public void pay() {
        System.out.println("支付宝支付");
    }
}

/**
 * description: 微信支付
 */
public class WxPay implements IPay {
    public void pay() {
        System.out.println("微信支付");
    }
}

/**
 * description: 银联支付
 */
public class UniPay implements IPay {
    public void pay() {
        System.out.println("银联支付");
    }
}

/**
 * description: 苹果支付
 */
public class ApplePay implements IPay {
    public void pay() {
        System.out.println("苹果支付");
    }
}

/**
 * description: 支付抽象工厂
 */
public abstract class AbstractPayFactory {
    public void init() {
        System.out.println("初始化基础数据");
    }
}

/**
 * description: 国内支付
 */
public class ChinaPayFactory extends AbstractPayFactory {
    protected IPay createAliPay() {
        super.init();
        return new AliPay();
    }

    protected IPay createWxPay() {
        super.init();
        return new WxPay();
    }

    protected IPay createUniPay() {
        super.init();
        return new UniPay();
    }
}

/**
 * description: 国外支付
 */
public class ForeignPayFactory extends AbstractPayFactory {
    protected IPay createApplePay() {
        super.init();
        return new ApplePay();
    }
}

/**
 * description: 抽象工厂方法测试
 */
public class AbstractPayFactoryTest {
    public static void main(String[] args) {
        ChinaPayFactory chinaPayFactory = new ChinaPayFactory();
        chinaPayFactory.createAliPay().pay();
        chinaPayFactory.createWxPay().pay();
        chinaPayFactory.createUniPay().pay();

        ForeignPayFactory foreignPayFactory = new ForeignPayFactory();
        foreignPayFactory.createApplePay().pay();
    }
}

추천

출처www.cnblogs.com/amiaojiang/p/12363956.html