一:简单工厂模式
专⻔定义⼀个类⽤来创建其它类的实例,被创建的实例通常都具有共同的⽗类。
优点:
简单易于实现
把类的实例化交给⼯⼚,易于解耦
缺点:
添加具体产品需要修改⼯⼚违反OCP开放封闭原则
import java.util.Scanner;
public interface Computer {
void outputcompuyer();
}
class ProComputer implements Computer{
@Override
public void outputcompuyer() {
System.out.println("这是一个苹果电脑");
}
}
class MiComputer implements Computer{
@Override
public void outputcompuyer() {
System.out.println("这是一个小米电脑");
}
}
class ComputerFactory {
public static Computer input(String type){
Computer computer = null;
if (type.equals("Pro")){
computer = new ProComputer();
}
if (type.equals("Mi")){
computer = new MiComputer();
}
return computer;
}
} //工厂对象的选择
class Client{
public void BuyComputer(Computer computer){
computer.outputcompuyer();
} //具体对象的输出
public static void main(String[] args) {
Client client = new Client(); //得到一个对象
Scanner scanner = new Scanner(System.in);
System.out.println("请输入Pro 或者 Mi 来选择电脑型号");
String type = scanner.nextLine(); //键盘输入想要的型号
Computer computer = ComputerFactory.input(type); //取得工厂中对应的对象
client.BuyComputer(computer); //具体对象的输出
}
}
二:工厂方法模式
⼯⼚⽅法模式是针对每个产品提供⼀个⼯⼚类,在客户端中判断使⽤哪个⼯⼚类去创建对象。
简单⼯⼚模式 VS ⼯⼚⽅法模式:
1.对于简单⼯⼚模式⽽⾔,创建对象的逻辑判断放在了⼯⼚类中,客户不感知具体的类,但是其违背了开闭原则,如果要增加新的具体类,就必须修改⼯⼚类。
2.对于⼯⼚⽅法模式⽽⾔,是通过扩展来新增具体类的,符合开闭原则,但是在客户端就必须要感知到具体的⼯⼚类,也就是将判断逻辑由简单⼯⼚的⼯⼚类挪到客户端。
3.⼯⼚⽅法横向扩展很⽅便,假如该⼯⼚⼜有新的产品 Macbook Air 要⽣产,那么只需要创建相应的⼯⼚类和产品类去实现抽象⼯⼚接⼝和抽象产品接⼝即可,⽽不⽤去修改原有已经存在的代码
具体代码示例:
public interface Computer { void outputcompuyer(); } //定义了一个名为电脑接口 class ProComputer implements Computer{ @Override public void outputcompuyer() { System.out.println("这是一个苹果电脑"); } } //第一个实现电脑接口 class MiComputer implements Computer{ @Override public void outputcompuyer() { System.out.println("这是一个小米电脑"); } } //第二个实现电脑接口 interface ComputerFactory { Computer createComputer(); } //定义了一个名为计算机工厂接口 class Linux implements ComputerFactory{ @Override public Computer createComputer() { return new MiComputer(); } } //第一种实现计算机工厂接口 class ProFactory implements ComputerFactory{ @Override public Computer createComputer() { return new ProComputer(); } //第二种实现计算机工厂接口 } class Client { public void BuyComputer(Computer computer) { computer.outputcompuyer(); } //具体对象的输出 public static void main(String[] args) { Client client = new Client(); //得到一个具体输出的对象 ComputerFactory factory = new ProFactory(); ComputerFactory factory1 = new Linux(); //得到一个计算机工厂类接口所创建的实现他的子类对象 client.BuyComputer(factory.createComputer()); client.BuyComputer(factory1.createComputer()); /*具体输出的对象调用自己的方法 它的参数应该是Computer 类型 而 factory 对象所调用的方法就是Computer 类型 所以直接拿来使用*/ /* 值得注意的是,这种方法的使用必须事先知道自己所想要实现的对象是哪一种, 如想要得到 MiComputer 就需要目标明确的 new Linux() 对象从而实现。*/ } }
优点:
降低了代码耦合度,对象的⽣成交给⼦类去完成
实现了开放封闭原则 - 每次添加⼦产品 不需要修改原有代码
缺点:
增加了代码量,每个具体产品都需要⼀个具体⼯⼚
当增加抽象产品 也就是添加⼀个其他产品族 需要修改⼯⼚ 违背OC
三:抽象工厂模式
抽象⼯⼚模式:提供⼀个创建⼀系列相关或相互依赖对象的接⼝,⽽⽆需指定它们具体的类。
⼯⼚⽅法模式和抽象⼯⼚模式基本类似,可以这么理解:当⼯⼚只⽣产⼀个产品的时候,即为⼯⼚⽅法模式,⽽⼯⼚如果⽣产两个或以上的商品即变为抽象⼯⼚模式。
public interface Computer { void outputcompuyer(); } //定义了一个名为电脑接口 class ProComputer implements Computer{ @Override public void outputcompuyer() { System.out.println("这是一个苹果电脑"); } } //第一个实现电脑接口 class MiComputer implements Computer{ @Override public void outputcompuyer() { System.out.println("这是一个小米电脑"); } } //第二个实现电脑接口 interface OperatingSystem{ void outSystem(); } //定义了一个名为系统的接口 class LinuxSystem implements OperatingSystem{ @Override public void outSystem() { System.out.println("它支持Linux系统"); } } //第一个实现系统接口的Linux类 class IosSystem implements OperatingSystem{ @Override public void outSystem() { System.out.println("它支持Ios系统"); } } //第二个实现系统接口的IOS类 interface ComputerFactory { Computer createComputer(); OperatingSystem createSystem(); } //定义了一个名为计算机工厂接口 class MiBookComputer implements ComputerFactory{ @Override public Computer createComputer() { return new MiComputer(); } @Override public OperatingSystem createSystem() { return new LinuxSystem(); } } //第一种实现计算机工厂接口 class ProbookComputer implements ComputerFactory{ @Override public Computer createComputer() { return new ProComputer(); } @Override public OperatingSystem createSystem() { return new IosSystem(); } } //第二种实现计算机工厂接口 class Client { public void BuyComputer(Computer computer) { computer.outputcompuyer(); } //具体对象的输出 public void use (OperatingSystem s){ s.outSystem(); } //具体对象的输出 public static void main(String[] args) { Client client = new Client(); //得到一个具体输出的对象 ComputerFactory factory = new MiBookComputer(); //实例化一个具体的已知目标对象 //得到一个计算机工厂类接口所创建的实现他的子类对象 Computer computer = factory.createComputer(); OperatingSystem system = factory.createSystem(); client.BuyComputer(computer); client.use(system); //调用符合自己参数类型的变量,而变量则是通过已经实例化的对象的方法来实现 } }
优点:
代码解耦
实现多个产品族(相关联产品组成的家族),⽽⼯⼚⽅法模式的单个产品,可以满⾜更多的⽣产需求
很好的满⾜OCP开放封闭原则
抽象⼯⼚模式中我们可以定义实现不⽌⼀个接⼝,⼀个⼯⼚也可以⽣成不⽌⼀个产品类 对于复杂
对象的⽣产相当灵活易扩展
缺点:
扩展产品族相当麻烦 ⽽且扩展产品族会违反OCP,因为要修改所有的⼯⼚
由于抽象⼯⼚模式是⼯⼚⽅法模式的扩展 总体的来说 很笨重
四:工厂模式总结
简单⼯⼚模式最⼤的优点就是⼯⼚内有具体的逻辑去判断⽣成什么产品,将类的实例化交给了⼯
⼚,这样当我们需要什么产品只需要修改⼯⼚的调⽤⽽不需要去修改客户端,对于客户端来说降
低了与具体产品的依赖
⼯⼚⽅法模式是简单⼯⼚的扩展,⼯⼚⽅法模式把原先简单⼯⼚中的实现那个类的逻辑判断交给
了客户端,如果像添加功能只需要修改客户和添加具体的功能,不⽤去修改之前的类。
抽象⼯⼚模式进⼀步扩展了⼯⼚⽅法模式,它把原先的⼯⼚⽅法模式中只能有⼀个抽象产品不能
添加产品族的缺点克服了,抽象⼯⼚模式不仅仅遵循了OCP原则,⽽且可以添加更多产品(抽象产
品),具体⼯⼚也不仅仅可以⽣成单⼀产品,⽽是⽣成⼀组产品,抽象⼯⼚也是声明⼀组产品,对应
扩展更加灵活,但是要是扩展族系就会很笨重。
五:代理设计模式
两个⼦类共同实现⼀个接⼝,其中⼀个⼦类负责真实业务实现,另外⼀个⼦类完成辅助真实业务主题的
操作。
代码实例:
public interface Isubject { void outComputer(); } //定义一个被实现的接口 class realSubject implements Isubject{ @Override public void outComputer() { System.out.println("买一个华为电脑"); } } //真实实现接口 class ProxySubject implements Isubject{ //辅助继承接口 private Isubject isubject; //定义一个私有的属性 public ProxySubject(Isubject isubject){ this.isubject = isubject; } //构造函数 public void beforeSellComputer(){ System.out.println("出售电脑前的准备"); } //成员方法一 public void afterSellComputer(){ System.out.println("售后服务"); } //成员方法二 @Override public void outComputer() { this.beforeSellComputer(); this.isubject.outComputer(); this.afterSellComputer(); } //实现继承的接口的那个类 } class Factry{ public static Isubject getInstance(){ return new ProxySubject(new realSubject()); } //重点:生成辅助类的构造函数,形参为真实类对象 //作用:将ProxySubject.outComputer中的这句this.isubject.outComputer(); //让他调用真实类中的函数而不是辅助类中的函数 //如果将new ProxySubject(new realSubject())中参数变为 //new ProxySubject(new ProxySubject()) 则会发生编译出错。 } class TestDamo1{ public static void main(String[] args) { Isubject subject = Factry.getInstance(); subject.outComputer(); //生成Isubject类对象并让其调用辅助类中的成员方法 } }
代理模式的本质:所有的真实业务操作都会有⼀个与之辅助的⼯具类(功能类)共同完成。